# frozen_string_literal: true

module TTY
  module Color
    class Mode
      TERM_24BIT = /[+-]direct/.freeze
      TRUECOLORS = 2**24 # 8 bits per RGB channel

      TERM_256 = /^(alacritty|iTerm\s?\d*\.app|kitty|mintty|ms-terminal|
                    nsterm|nsterm-build\d+|terminator|terminology(-[0-9.]+)?|
                    termite|vscode)$/x.freeze

      TERM_64 = /^(hpterm-color|wy370|wy370-105k|wy370-EPC|wy370-nk|
                   wy370-rv|wy370-tek|wy370-vb|wy370-w|wy370-wvb)$/x.freeze

      TERM_52 = /^(dg+ccc|dgunix+ccc|d430.*?[-+](dg|unix).*?[-+]ccc)$/x.freeze

      TERM_16 = /^(amiga-vnc|d430-dg|d430-unix|d430-unix-25|d430-unix-s|
                 d430-unix-sr|d430-unix-w|d430c-dg|d430c-unix|d430c-unix-25|
                 d430c-unix-s|d430c-unix-sr|d430c-unix-w|d470|d470-7b|d470-dg|
                 d470c|d470c-7b|d470c-dg|dg+color|dg\+fixed|dgunix\+fixed|
                 dgmode\+color|hp\+color|ncr260wy325pp|ncr260wy325wpp|
                 ncr260wy350pp|ncr260wy350wpp|nsterm-c|nsterm-c-acs|
                 nsterm-c-s|nsterm-c-s-7|nsterm-c-s-acs|nsterm\+c|
                 nsterm-7-c|nsterm-bce)$/x.freeze

      TERM_8 = /vt100|xnuppc|wy350/x.freeze

      METHODS = %w[from_term from_tput].freeze

      def initialize(env)
        @env = env
      end

      # Detect supported colors
      #
      # @return [Integer]
      #   out of 0, 8, 16, 52, 66, 256, 2^24
      #
      # @api public
      def mode
        return 0 unless TTY::Color.tty?

        value = 8
        METHODS.each do |from_check|
          break if (value = public_send(from_check)) != NoValue
        end
        return 8 if value == NoValue
        value
      end

      # Check TERM environment for colors
      #
      # @return [NoValue, Integer]
      #
      # @api private
      def from_term
        case @env["TERM"]
        when TERM_24BIT then TRUECOLORS
        when /[-+](\d+)color/ then $1.to_i
        when /[-+](\d+)bit/   then 2**$1.to_i
        when TERM_256 then 256
        when TERM_64  then 64
        when TERM_52  then 52
        when TERM_16  then 16
        when TERM_8   then 8
        when /dummy/  then 0
        else NoValue
        end
      end

      # Shell out to tput to check color support
      #
      # @return [NoValue, Integer]
      #
      # @api private
      def from_tput
        return NoValue unless TTY::Color.command?("tput colors")

        colors = `tput colors 2>/dev/null`.to_i
        colors >= 8 ? colors : NoValue
      rescue Errno::ENOENT
        NoValue
      end
    end # Mode
  end # Color
end # TTY
