require "httpclient"
require "exceptions/devops_exception"
require "exceptions/not_found"
require "exceptions/invalid_query"
require "devops-client/options/common_options"
require "uri"
require "json"
require "devops-client/i18n"
require "devops-client/handler/helpers/input_utils"
require "devops-client/handler/helpers/colored_output_utils"
require "devops-client/handler/helpers/http_utils"
require "devops-client/handler/helpers/outputtable"
require "devops-client/handler/helpers/resources_fetcher"
require "devops-client/handler/helpers/resources_selector"
require "devops-client/providers/providers"

class Handler

  include InputUtils
  include ColoredOutputUtils
  include HttpUtils
  include Outputtable

  attr_reader :options
  attr_writer :host
  attr_accessor :auth, :command

  def host
    if @host.start_with?('http')
      @host
    else
      "http://#{@host}"
    end
  end

  #TODO: only basic auth now
  def username
    self.auth[:username]
  end

  def password
    self.auth[:password]
  end

  def options= o
    self.host = o.delete(:host) if o.has_key? :host
    @options = o
  end

protected

  def resources_selector
    @resources_selector ||= Helpers::ResourcesSelector.new(fetcher)
  end

  def fetcher
    @fetcher ||= Helpers::ResourcesFetcher.new(host: @host, handler_options: @options, auth: @auth)
  end

  # Parameters
  #   PARAM - mandatory parameter, will be available by variable @param
  #   [PARAM] - not mandatory parameter, will be available by variable @param (can be nil)
  #   PARAM... - mandatory parameters, will be available by variable @param, it is array with one or more elements
  #   [PARAM...] - not mandatory parameters, will be available by variable @param, it is array with one or more elements or nil
  def extract_parameters
    cmd = @command
    names = @options_parser.send("#{cmd}_params")
    return unless names
    names.each_with_index do |name, i|
      if name.start_with? "[" and name.end_with? "]"
        param_name = name.delete("[]")
        if param_name.end_with? "..."
          param_name = param_name.delete(".")
          instance_variable_set "@" + param_name.downcase, @args[i..-1]
          return
        end
      elsif name.end_with? "..."
        param_name = name.delete(".")
        instance_variable_set "@" + param_name.downcase, @args[i..-1]
        return
      else
        if @args[i].nil? or @args[i].empty?
          @options_parser.send("invalid_#{cmd}_command")
          res = "\n" + I18n.t("handler.error.parameter.undefined", :name => name)
          abort(res)
        end
        param_name = name
      end
      instance_variable_set "@" + param_name.downcase, @args[i]
    end
    nil
  end

  def check_status status
    r = status.scan(/--\sStatus:\s([0-9]{1,5})\s--/i)[0]
    if r.nil?
      puts "WARN: status undefined"
      -1
    else
      r[0].to_i
    end
  end

end
