# lib/aia/cli.rb

module AIA::Cli
  def setup_cli_options(args)
    @arguments  = args
    @options    = {
      #           Value
      edit?:      [false, "-e --edit",    "Edit the Prompt File"],
      debug?:     [false, "-d --debug",   "Turn On Debugging"],
      verbose?:   [false, "-v --verbose", "Be Verbose"],
      version?:   [false, "--version",    "Print Version"],
      help?:      [false, "-h --help",    "Show Usage"],
      fuzzy?:     [false, "--fuzzy",      "Use Fuzzy Matching"],
      # TODO: Consider dropping output in favor of always
      #       going to STDOUT so user can redirect or pipe somewhere else
      output:     [OUTPUT,"-o --output --no-output",  "Out FILENAME"],
      log:        [PROMPT_LOG,"-l --log --no-log", "Log FILEPATH"],
      markdown?:  [true,  "-m --markdown --no-markdown --md --no-md", "Format with Markdown"],
    }
    
    # Array(String)
    @extra_options = [] # intended for the backend AI processor

    build_reader_methods # for the @options keys      
    process_arguments
  end


  def usage
    usage =   "\n#{MY_NAME} v#{AIA::VERSION}\n\n"
    usage +=  "Usage:  #{MY_NAME} [options] prompt_id [context_file]* [-- external_options+]\n\n"
    usage +=  usage_options
    usage += "\n"
    usage += usage_notes if verbose?
    
    usage
  end
 

  def usage_options
    options = [
      "Options",
      "-------",
      ""
    ]

    max_size = @options.values.map{|o| o[2].size}.max + 2

    @options.values.each do |o|
      pad_size = max_size - o[2].size
      options << o[2] + (" "*pad_size) + o[1]

      default = o[0]
      default = "./" + default.basename.to_s if o[1].include?('output')
      default = default.is_a?(Pathname) ? "$HOME/" + default.relative_path_from(HOME).to_s : default

      options << " default: #{default}\n"
    end

    options.join("\n")
  end


  def usage_notes
    <<~EOS
      #{usage_envars}
      #{AIA::ExternalCommands::HELP}
    EOS
  end


  def usage_envars
    <<~EOS
      System Environment Variables Used
      ---------------------------------

      The OUTPUT and PROMPT_LOG envars can be overridden
      by cooresponding options on the command line.

      Name            Default Value
      --------------  -------------------------
      PROMPTS_DIR     $HOME/.prompts_dir
      AI_CLI_PROGRAM  mods
      EDITOR          edit
      MODS_MODEL      gpt-4-1106-preview
      OUTPUT          ./temp.md
      PROMPT_LOG      $PROMPTS_DIR/_prompts.log

      These two are required for access the OpenAI
      services.  The have the same value but different
      programs use different envar names.

      To get an OpenAI access key/token (same thing)
      you must first create an account at OpenAI.
      Here is the link:  https://platform.openai.com/docs/overview

      OPENAI_ACCESS_TOKEN
      OPENAI_API_KEY

    EOS
  end


  def build_reader_methods
    @options.keys.each do |key|
      define_singleton_method(key) do
        @options[key][0]
      end
    end
  end


  def process_arguments
    @options.keys.each do |option|
      check_for option
    end

    # get the options meant for the backend AI command
    extract_extra_options

    bad_options = @arguments.select{|a| a.start_with?('-')}

    unless bad_options.empty?
      puts <<~EOS

        ERROR: Unknown options: #{bad_options.join(' ')}

      EOS
      
      show_usage

      exit
    end
  end


  def check_for(option_sym)
    boolean = option_sym.to_s.end_with?('?')
    switches = @options[option_sym][1].split

    switches.each do |switch|
      if @arguments.include?(switch)
        index = @arguments.index(switch)

        if boolean
          @options[option_sym][0] = switch.include?('-no-') ? false : true
          @arguments.slice!(index,1)
        else
          if switch.include?('-no-')
            @options[option_sym][0] = nil
            @arguments.slice!(index,1)
          else
            @options[option_sym][0] = @arguments[index + 1]
            @arguments.slice!(index,2)
          end
        end
        
        break
      end
    end
  end



  def show_usage
    @options[:help?][0] = false 
    puts usage
    exit
  end
  alias_method :show_help, :show_usage


  def show_version
    puts AIA::VERSION
    exit
  end
end


__END__


# TODO: Consider using this history process to preload the default
#       so that an up arrow will bring the previous answer into
#       the read buffer for line editing.
#       Instead of usin the .history file just push the default
#       value from the JSON file.

while input = Readline.readline('> ', true)
  # Skip empty entries and duplicates
  if input.empty? || Readline::HISTORY.to_a[-2] == input
    Readline::HISTORY.pop
  end
  break if input == 'exit'

  # Do something with the input
  puts "You entered: #{input}"

  # Save the history in case you want to preserve it for the next sessions
  File.open('.history', 'a') { |f| f.puts(input) }
end

# Load history from file at the beginning of the program
if File.exist?('.history')
  File.readlines('.history').each do |line|
    Readline::HISTORY.push(line.chomp)
  end
end