#!/usr/bin/ruby -w
# Encoding: UTF-8
# frozen_string_literal: true
# =========================================================================== #
# require 'colours/html_colours/html_colours.rb'
# Colours.map_this_symbol_to_that_html_colour
# Colours.autogenerate_html_colours_methods
# =========================================================================== #
module Colours

module HtmlColours # === Colours::HtmlColours

  # ========================================================================= #
  # This module will also try to pull in the autogenerated
  # Colours::HtmlColoursMethods module, if available.
  # ========================================================================= #
  begin
    require 'colours/autogenerated/html_colours_methods.rb'
  rescue LoadError
    # puts 'No file exists at `colours/autogenerated/html_colours_methods.rb`.'
  end

  require 'colours/toplevel_methods/e.rb'
  require 'colours/toplevel_methods/map_this_symbol_to_that_html_colour.rb'
  require 'colours/toplevel_methods/rev.rb'
  require 'colours/html_colours/hash_html_colours.rb'
  require 'colours/html_colours/random_html_colour.rb'

  # ========================================================================= #
  # === Colours::HtmlColours.rev
  # ========================================================================= #
  def self.rev
    ::Colours.rev
  end

  # ========================================================================= #
  # === Colours::HtmlColours.e
  # ========================================================================= #
  def self.e(i = '')
    ::Colours.e(i)
  end

  # ========================================================================= #
  # === all_html_colours
  #
  # This method will feedback all html colours known.
  # ========================================================================= #
  def all_html_colours
    ::Colours::HtmlColours.available_html_colours?
  end; alias all_html_colours? all_html_colours # === all_html_colours?
       alias html_colours?     all_html_colours # === html_colours?
       alias all_colours       all_html_colours # === all_colours

  # ========================================================================= #
  # === Colours::HtmlColours.autogenerate_html_colours_methods (autogenerate tag)
  #
  # This method will autogenerated all HTML colours, onto the toplevel
  # namespace called "Colours".
  #
  # Commandline invocation example:
  #
  #   colours --autogenerate_html_colours_methods
  #
  # ========================================================================= #
  def self.autogenerate_html_colours_methods(
      into = HOME_DIRECTORY_OF_USER_X+
             'programming/ruby/src/'\
             'colours/lib/colours/autogenerated/'\
             'html_colours_methods.rb'
    )
    require 'colours/requires/require_save_file.rb'
    dataset_from_the_yaml_file = YAML.load_file(::Colours.file_html_colours)
    _ = "#{RUBY_HEADER}\n".dup
    _ << "# require 'colours/autogenerated/#{File.basename(into)}'\n"
    _ << "# =========================================================================== #\n"
    _ << "# include ::Colours::HtmlColoursMethods\n"
    _ << "# =========================================================================== #\n"
    _ << "module Colours\n\n"
    _ << "module HtmlColoursMethods # === ::Colours::HtmlColoursMethods\n\n"

    ::Colours::HtmlColours.all_html_colours?.each {|this_html_colour|
      # ===================================================================== #
      # We must obtain the proper entry from the .yml file next:
      # ===================================================================== #
      pointer = dataset_from_the_yaml_file[this_html_colour.to_s]
      r = pointer[0]
      g = pointer[1]
      b = pointer[2]
      _ << "  # ========================================================================= #\n"
      _ << "  # === Colours::HtmlColoursMethods.#{this_html_colour}\n"
      _ << "  # ========================================================================= #\n"
      _ << "  def self.#{this_html_colour}(i = '', &block)\n"
      # ===================================================================== #
      # The colour code goes like this:
      #
      #   \033[38;2;<R>;<G>;<B>m
      #
      # ===================================================================== #
      _ << '    return "'+
           '\e[38;2;'+
           "#{r};#{g};#{b}m"+ # ← Here the r,g,b values. 'm' terminates the escape sequence.
           "#\{i\}\""+
           " if block_given? and (yield == :omit_end)"+
           "\n"
      _ << '    return "'+
           '\e[38;2;'+
           "#{r};#{g};#{b}m"+ # ← Here the r,g,b values. 'm' terminates the escape sequence.
           "#\{i\}"+
           "\\e[0m"+
           "\"\n"
      _ << "  end\n\n"
    }
    _ << "end\n\n"
    _ << "end\n"
    e "Storing into the file `#{into}` next."
    SaveFile.write_what_into(_, into)
    autogenerate_html_colours_methods_for_instance_methods
  end

  # ========================================================================= #
  # === Colours::HtmlColours.autogenerate_html_colours_methods_for_instance_methods
  #
  # On my home system I can use this command to trigger this method:
  #
  #   autogenerate_html_colours_methods
  #
  # ========================================================================= #
  def self.autogenerate_html_colours_methods_for_instance_methods(
      into = HOME_DIRECTORY_OF_USER_X+
             'programming/ruby/src/'\
             'colours/lib/colours/autogenerated/'\
             'html_colours_instance_methods.rb'
    )
    require 'colours/requires/require_save_file.rb'
    _ = "#{RUBY_HEADER}\n".dup
    _ << "# require 'colours/autogenerated/#{File.basename(into)}'\n"
    _ << "# =========================================================================== #\n"
    _ << "# include ::Colours::HtmlColoursMethods\n"
    _ << "# =========================================================================== #\n"
    _ << "module Colours\n\n"
    _ << "module HtmlColoursMethods # === ::Colours::HtmlColoursMethods\n\n"

    ::Colours::HtmlColours.all_html_colours?.each {|this_html_colour|
      _ << "  # ========================================================================= #\n"
      _ << "  # === #{this_html_colour}\n"
      _ << "  # ========================================================================= #\n"
      _ << "  def #{this_html_colour}(i = '', &block)\n"
      _ << "    return ::Colours::HtmlColoursMethods.#{this_html_colour}(i, &block)\n"
      _ << "  end; alias konsole_colour_#{this_html_colour} #{this_html_colour}\n"
      _ << "       alias konsole_#{this_html_colour} #{this_html_colour}\n\n"
    }
    _ << "end\n\n"
    _ << "end\n"
    e "Storing into the file `#{into}` next."
    SaveFile.write_what_into(_, into)
  end

  # ========================================================================= #
  # === Colours::HtmlColours.show_html_colours
  #
  # This can be used to output the colours. It requires the method
  # html_colours() as well as support for RGB values.
  #
  # To invoke this method from the commandline, try:
  #
  #   colours --show_html_colours
  #
  # ========================================================================= #
  def self.show_html_colours
    require 'colours/rgb/rgb.rb'
    lpad = 22
    show_this_standard_sentence =
      'This is a longer test-sentence in that colour.'
    print '  '; e '=' * 100
    html_colours.each {|this_html_colour|
      result = "#{::Colours.rgb_as_string(this_html_colour)} #{this_html_colour.to_s.ljust(22)}"
      # ===================================================================== #
      # Next, show that particular colour.
      # ===================================================================== #
      string = ::Colours.rgb_as_string(this_html_colour).strip
      ansi_escape_code = string.tr("\e","\\e")
      display_this_line =
        "  | #{(this_html_colour+': ').ljust(lpad)}| "\
        "#{result}#{::Colours.rev} | #{::Colours.rgb_as_string(this_html_colour)}#{show_this_standard_sentence}#{rev} |\n".dup # rev() is needed to restore the old default.
      display_this_line << '  |                       | '
      display_this_line << ''.ljust(22)
      echo_string = "  |   echo -e \""+string+"\\"+ansi_escape_code+"xyz#{rev}"+'"'
      padded_echo_string = (echo_string.rstrip).ljust(72)
      display_this_line << "#{padded_echo_string}|"
      e display_this_line
    }
    print '  '; e '=' * 100
  end; self.instance_eval { alias display_all_colours show_html_colours } # === Colours::HtmlColours.display_all_colours
       self.instance_eval { alias show_colours        show_html_colours } # === Colours::HtmlColours.show_colours
       self.instance_eval { alias test                show_html_colours } # === Colours::HtmlColours.test
       self.instance_eval { alias show_all_colours    show_html_colours } # === Colours::HtmlColours.show_all_colours

  # ========================================================================= #
  # === Colours::HtmlColours.html_colourize
  # ========================================================================= #
  def self.html_colourize(i)
    if i.is_a? Array
      i = i.join(' ')
    end
    if i
      if File.file?(i)
        i = File.read(i)
      elsif i.respond_to? :read
        i = i.read
      end
    end
    if i.is_a? String
      # ===================================================================== #
      # Find all HTML colours next in that String:
      # ===================================================================== #
      splitted = i.split("\n")
      splitted.map! {|entry|
        if ::Colours.does_this_line_include_a_html_colour?(entry)
          entry = ::Colours.replace_all_raw_html_colours_in_this_line(entry)
        end
        entry
      }
      i = splitted.join("\n")
    end
    e i
  end

  # ========================================================================= #
  # === Colours::HtmlColours.colour_to_rgb
  #
  # This method will convert the long colour name to an Array
  # with R,G,B values.
  #
  # Usage examples:
  #
  #  Colours::HtmlColours.colour_to_rgb('whitesmoke') # => [245, 245, 245]
  #  Colours::HtmlColours.colour_to_rgb('slateblue')  # => [106, 90, 205]
  #  Colours::HtmlColours.colour_to_rgb(:royalblue)   # => [65, 105, 225]
  #
  # ========================================================================= #
  def self.colour_to_rgb(
      long_name = :slateblue
    )
    pointer = @dataset[long_name.to_s] # This will be an Array.
    return [pointer[0], pointer[1], pointer[2]]
  end; self.instance_eval { alias to_rgb colour_to_rgb } # === HtmlColours.to_rgb()

  # ========================================================================= #
  # === Colours::HtmlColours[]
  #
  # Easier toplevel-access method, through [].
  #
  # The second message is the text that you wish to display.
  #
  # Usage examples:
  #
  #   Colours::HtmlColours['slateblue','Hello World!'] # works as Example 1
  #   Colours::HtmlColours['slateblue']
  #   Colours::HtmlColours['lightgreen','Hello World!']
  #   Colours::HtmlColours[:random]
  #   e Colours::HtmlColours[:random, 'yo there']
  #   e Colours::HtmlColours[:steelblue, 'yo there']
  #
  # ========================================================================= #
  def self.[](
      use_this_colour   = :slateblue,
      display_this_text = ''
    )
    case use_this_colour
    # ======================================================================= #
    # === :random
    # ======================================================================= #
    when :random
      use_this_colour = random_html_colour
    end
    ::Colours::HtmlColoursMethods.send(
      use_this_colour,
      display_this_text
    )
  end

end

# =========================================================================== #
# === available_html_colours?
# =========================================================================== #
def available_html_colours?
  ::Colours.available_html_colours?
end; alias all_html_colours?       available_html_colours? # === all_html_colours?
     alias html_colours?           available_html_colours? # === html_colours?
     alias html_colours            available_html_colours? # === html_colours
     alias all_html_colours        available_html_colours? # === all_html_colours
     alias return_all_html_colours available_html_colours? # === return_all_html_colours
     alias colours?                available_html_colours? # === colours?
     alias colours                 available_html_colours? # === colours
     alias registered_colours?     available_html_colours? # === registered_colours?

# =========================================================================== #
# === Colours.show_html_colours
# =========================================================================== #
def self.show_html_colours
  ::Colours::HtmlColours.show_html_colours
end; self.instance_eval { alias display_all_colours show_html_colours } # === Colours.display_all_colours
     self.instance_eval { alias show_colours        show_html_colours } # === Colours.show_colours
     self.instance_eval { alias test                show_html_colours } # === Colours.test
     self.instance_eval { alias show_all_colours    show_html_colours } # === Colours.show_all_colours

# =========================================================================== #
# === show_html_colours
# =========================================================================== #
def show_html_colours
  ::Colours.show_html_colours
end

# =========================================================================== #
# === Colours.colour_to_rgb
# =========================================================================== #
def self.colour_to_rgb(i = :slateblue)
  ::Colours::HtmlColours.colour_to_rgb(i)
end; self.instance_eval { alias to_rgb colour_to_rgb } # === Colours.to_rgb()

# =========================================================================== #
# === Colours.does_this_line_include_a_html_colour?
#
# This method can be used to determine whether the given input-string
# contains a valid HTML colour or whether it does not.
#
# Returns: a boolean.
#
# Invocation examples:
#
#   Colours.does_this_line_include_a_html_colour? "<green>yo there</green> <orange>getline() function</orange>" # => true
#   Colours.does_this_line_include_a_html_colour? "foo bar" # => false
#
# =========================================================================== #
def self.does_this_line_include_a_html_colour?(
    line
  )
  html_colours?.any? {|entry|
    line.include? entry
  }
end

# =========================================================================== #
# === random_colour?
# =========================================================================== #
def random_colour?
  return Colours.random_html_colour
end; alias return_random_html_colour random_colour? # === return_random_html_colour
     alias random_html_colour        random_colour? # === random_html_colour
     alias random_colour             random_colour? # === random_colour
     alias random                    random_colour? # === random
     alias sample                    random_colour? # === sample

# =========================================================================== #
# === Colours.autogenerate_html_colours_methods
# =========================================================================== #
def self.autogenerate_html_colours_methods
  ::Colours::HtmlColours.autogenerate_html_colours_methods
end; self.instance_eval { alias autogenerate_the_module_for_the_html_colours autogenerate_html_colours_methods } # === Colours.autogenerate_the_module_for_the_html_colours

end

if __FILE__ == $PROGRAM_NAME
  alias e puts
  dataset = Colours::HtmlColours.dataset?
  pp dataset
  _ = Colours::HtmlColours.available_html_colours?
  e _.size.to_s+' HTML colours are registered.'
  e 'Is slateblue a HTML colour? '+
    Colours::HtmlColours.does_include?('slateblue').to_s
  e
  pp Colours::HtmlColours.colour_to_rgb('whitesmoke') # => [245, 245, 245]
  pp Colours::HtmlColours.colour_to_rgb('slateblue')  # => [106, 90, 205]
  pp Colours::HtmlColours.colour_to_rgb(:royalblue)   # => [65, 105, 225]
  e
  e 'Picking a random HTML colour next: '+
    Colours::HtmlColours.random_colour?
  e
  pp Colours::HtmlColours.return_all_html_colours
  p Colours.return_all_html_colours
  pp Colours::HtmlColours.colour_to_rgb('royalblue')
  e
  if ARGV.first
    p Colours::HtmlColours[ARGV.first]
  else
    print 'sienna -> '; pp Colours::HtmlColours.colour_to_rgb(:sienna)
    Colours::HtmlColours.show_all_colours
    p Colours::HtmlColours['sienna']
    e
    Colours::HtmlColours.show_html_colours
    e
  end
  # puts Colours.random_html_colour
  # puts Colours.random_html_colour
  # puts Colours.random_html_colour
  # pp Colours::HtmlColours.available_html_colours?
  # pp Colours::HtmlColours.random_colour?
  pp Colours::HtmlColours.hash_html_colours?
  e
  Colours::HtmlColours.html_colourize(ARGF)
  e
  e Colours.does_this_line_include_a_html_colour? "<green>yo there</green> <orange>getline() function</orange>" # => true
  e Colours.does_this_line_include_a_html_colour? "foo bar" # => false
  e
end