require "devops-client/handler/provider"
require "devops-client/handler/image"
require "devops-client/handler/user"
require "devops-client/handler/helpers/validators"
require "devops-client/options/project_options"
require "json"
require "set"
require "devops-client/output/project"

class Project < Handler

  output_with Output::Project

  def initialize(host, def_options={})
    @host = host
    @options_parser = ProjectOptions.new(ARGV, def_options)
  end

  def handle
    @command, @options, @args = @options_parser.parse_options_for!
    extract_parameters
    case @command
    when :create
      create_handler
    when :delete
      delete_handler
    when :list
      list_handler
      output
    when :servers
      servers_handler
      output
    when :stacks
      stacks_handler
      output
    when :set_run_list
      set_run_list_handler
    when :show
      show_handler
      output
    when :update
      puts "TODO: update"
      exit
      update_handler
    when :user_add
      user_add_handler
    when :user_delete
      user_delete_handler
    when :archive
      archive_handler
    when :unarchive
      unarchive_handler
    when "test"
      test_handler
    end
  end

  def list_handler
    @list = get "/projects"
  end

  def delete_handler
    delete "/project/#{@project_id}" if question(I18n.t("handler.project.question.delete", :name => @project_id))
  end

  def show_handler
    @show = get("/project/#{@project_id}")
  end

  def archive_handler
    post "/project/#{@project_id}/archive"
  end

  def unarchive_handler
    post "/project/#{@project_id}/unarchive"
  end

  def update_handler
    r = inspect_parameters @options_parser.update_params, args[2], args[3]
    unless r.nil?
      @options_parser.invalid_update_command
      abort(r)
    end
    update_object_from_file "project", args[2], args[3]
  end

  def create_handler
    file = self.options[:file]
    unless file.nil?
      json = File.read(file)
      begin
        JSON.parse(json)
      rescue JSON::ParserError => e
        abort(I18n.t("handler.project.create.invalid_json", :file => file))
      end
      post_body("/project", json)
    else
      create_project
    end
  end

  def servers_handler
    @list = get "/project/#{@project_id}/servers"
  end

  def stacks_handler
    @list = get "/project/#{@project_id}/stacks"
  end

  def user_add_handler
    post "/project/#{@project_id}/users/add", @user_name
  end

  def user_delete_handler
    post "/project/#{@project_id}/users/delete", @user_name
  end

  def set_run_list_handler
    run_list = @run_list || []
    if run_list.empty?
      exit unless question(I18n.t("handler.project.question.run_list.empty"))
    else
      exit unless Validators.validate_run_list(run_list)
    end
    post "/project/#{@project_id}/run_list", run_list
  end

  def test_handler args
    r = inspect_parameters @options_parser.test_params, args[2], args[3]
    unless r.nil?
      @options_parser.invalid_test_command
      abort(r)
    end
    job_ids = post "/project/test/#{args[2]}/#{args[3]}"
    reports_urls(job_ids)
  end

  protected
  def create_project

    project = {:environments => [], :id => @project_id}
    project[:description] = options[:description] || enter_parameter_or_empty(I18n.t("handler.project.create.description") + ": ")
    project[:project_users] = if options[:project_users]
      options[:project_users]
    else
      if question(I18n.t("handler.project.create.question.users_choose"))
        #choose
        resources_selector.select_available_users(label: I18n.t("handler.project.create.users"))
      else
        #enter
        get_comma_separated_list(I18n.t("input.message.input_list", cmd: I18n.t("input.user.list")))
      end

    end

    project[:run_list] = if self.options[:run_list]
      abort("Invalid run list: '#{self.options[:run_list].join(",")}'") unless Validators.validate_run_list(self.options[:run_list])
      self.options[:run_list]
    else
      input_run_list
    end

    json = JSON.pretty_generate(project)
    post_body("/project", json) if question(I18n.t("handler.project.question.create")){puts json}
  end

  def data_to_output
    @list || @show || @test
  end
end
