#!/usr/bin/ruby -w
# Encoding: UTF-8
# frozen_string_literal: true
# =========================================================================== #
# === Colours::RainbowColours
# =========================================================================== #
# require 'colours/rainbow_colours/do_parse_via_rainbow_colours.rb'
# =========================================================================== #

module Colours

module RainbowColours

  require 'colours/toplevel_methods/toplevel_methods.rb'
  # ========================================================================= #
  # Require rainbow_colours specific code next:
  # ========================================================================= #
  require 'colours/rainbow_colours/check_for_trollop_being_available_or_exit.rb'
  require 'colours/rainbow_colours/constants.rb'
  require 'colours/rainbow_colours/paint_detected_mode.rb'
  require 'colours/rainbow_colours/report_errors.rb'

  begin
    require 'stringio'
  rescue LoadError; end

  begin
    require 'trollop'
  rescue LoadError; end

  # ========================================================================= #
  # === Colours::RainbowColours.do_parse_via_rainbow_colours
  #
  # This is the rainbow_colours initializer.
  # ========================================================================= #
  def self.do_parse_via_rainbow_colours(
      i = ARGV
    )
    check_for_trollop_being_available_or_exit
    # ======================================================================= #
    # Setup the trollop-parser instance next.
    # ======================================================================= #
    trollop_parser = Trollop::Parser.new {
      banner <<HEADER

Usage: rainbow_colours [OPTION]... [FILE]...

Display one or several files. Alternatively, obtain input via STDIN.

With no FILE, or when FILE is -, read standard input.

HEADER
      banner ''
      # ll | rainbowc -a
      opt :animate,   'Enable psychedelics',        short: 'a', :default => false
      opt :spread,    'Rainbow spread',             short: 'p', :default => DEFAULT_RAINBOW_SPREAD
      opt :freq,      'Rainbow frequency',          short: 'F', :default => 0.1
      opt :seed,      'Rainbow seed, 0 = random',   short: 'S', :default => 0
      opt :duration,  'Animation duration',         short: 'd', :default => 12
      opt :speed,     'Animation speed',            short: 's', :default => 20.0
      opt :invert,    'Invert fg and bg',           short: 'i', :default => false
      opt :truecolor, '24-bit (truecolor)',         short: 't', :default => false
      opt :force,     'Force color even when stdout is not a tty', short: 'f', :default => false
      opt :help,      'Show this help menu',        short: 'h'
      banner <<FOOTER

Examples:

  rainbow_colours f - g      Output f's contents, then stdin, then g's contents.
  rainbow_colours            Copy standard input to standard output.
  fortune | rainbow_colours  Display a rainbow cookie.

FOOTER
    } # End of the help-banner.
    # ======================================================================= #
    # Keep the Trollop instance assigned to the variable opts.
    # ======================================================================= #
    opts = Trollop.with_standard_exception_handling(trollop_parser) {
      begin
        o = trollop_parser.parse(i) # Parse the given input here.
      rescue Trollop::HelpNeeded # If we need some more help.
        string_io_buffer = StringIO.new
        trollop_parser.educate(string_io_buffer) # <- display the help message and then exit.
        string_io_buffer.rewind
        opts = {
          animate:  false,
          speed:     20,
          duration:  12,
          os:       rand(256),
          spread:   8.0,
          freq:     0.3
        }
        splitted = string_io_buffer.read.split("\n")
        ::Colours.cat(splitted, opts)
        e
        string_io_buffer.close # Close the buffer again.
        exit 1
      end
      o
    }

    p.die(:spread,   'must be >= 0.1') if opts[:spread]   < 0.1
    p.die(:duration, 'must be >= 0.1') if opts[:duration] < 0.1
    p.die(:speed,    'must be >= 0.1') if opts[:speed]    < 0.1

    # ======================================================================= #
    # Build up the option-hash next.
    # ======================================================================= #
    opts[:os] = opts[:seed]
    opts[:os] = rand(256) if opts[:os] == 0

    begin
      if ARGV.empty?
        files = [:stdin]
      else
        files = ARGV[0..-1]
      end
      files.each { |file|
        case file
        when '-', :stdin
          fd = ARGF
        end
        begin
          fd = File.open(file) unless fd == ARGF
          if $stdout.tty? or opts[:force]
            # =============================================================== #
            # Work on TTY terminals. This also includes terminals such
            # as KDE Konsole. The second argument are the options passed
            # towards Colours.cat().
            # =============================================================== #
            ::Colours.cat(fd, opts)
          else
            until fd.eof? do
              # ============================================================= #
              # Keep on writing the input to $stdout here.
              # ============================================================= #
              $stdout.write(fd.read(8192))
            end
          end
        rescue Errno::ENOENT
          report_no_such_file_or_directory(file)
          exit 1
        rescue Errno::EACCES
          report_permission_denied(file)
          exit 1
        rescue Errno::EISDIR
          report_is_a_directory(file)
          exit 1
        rescue Errno::EPIPE
          exit 1
        end
      }
    rescue Interrupt
    end
  end

end; end

if __FILE__ == $PROGRAM_NAME
  Colours::RainbowColours.do_parse_via_rainbow_colours(ARGV)
end # rainbow_colours
    # ll | rainbow_colours
    # ll | rainbow_colours -a