require 'devops-client/handler/handler'

require 'devops-client/options/stack_options'
require 'devops-client/output/stack'

class Stack < Handler

  output_with Output::Stack

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

  def handle
    @command, @options, @args = @options_parser.parse_options_for!
    extract_parameters
    case @command
    when :list
      list_handler
      output
    when :show
      show_handler
      output
    when :create
      create_handler
    when :delete
      delete_handler
    when :sync
      sync_handler
      output
    when :deploy
      deploy_handler
    when :reserve
      reserve_handler
    when :unreserve
      unreserve_handler
    when :change_stack_template
      change_stack_template_handler
      output
    end
  end

  def create_handler
    attrs = {
      project: @project,
      environment: @environment,
      category: @category
    }
    category = fetcher.fetch_category(@project, @environment, @category)
    attrs[:provider] = category['provider']['name']
    attrs[:provider_account] = category['provider']['account']

    params_filepath = options[:parameters_file] || enter_parameter_or_empty(I18n.t('handler.stack.create.parameters_file'))
    if params_filepath.empty?
      attrs[:parameters] = {}
    else
      attrs[:parameters] = JSON.parse(File.read(params_filepath))
    end

    tags_filepath = options[:tags_file] || enter_parameter_or_empty(I18n.t('handler.stack.create.tags_file'))
    if tags_filepath.empty?
      attrs[:tags] = {}
    else
      attrs[:tags] = JSON.parse(File.read(tags_filepath))
    end

    json = JSON.pretty_generate(
      without_bootstrap: options[:without_bootstrap] || false,
      skip_rollback: options[:skip_rollback] || false,
      stack_attributes: attrs
    )
    if question(I18n.t("handler.stack.question.create")) {puts json}
      job_ids = post_body "/stack", json
      reports_urls(job_ids)
    end
  end

  def list_handler
    @list = if @options[:given_provider]
      provider_stacks(@options[:given_provider])
    else
      get("/stacks")
    end
  end

  def show_handler
    stack_id = @args[2]
    r = inspect_parameters(@options_parser.show_params, stack_id)
    unless r.nil?
      @options_parser.invalid_show_command
      abort(r)
    end
    @show = get "/stack/#{stack_id}"
  end

  def sync_handler
    stack_id = @args[2]
    r = inspect_parameters(@options_parser.sync_params, stack_id)
    unless r.nil?
      @options_parser.invalid_sync_command
      abort(r)
    end
    @show = post "/stack/#{stack_id}/sync"
  end

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

  def deploy_handler
    stack_id = @args[2]
    job_ids = post "/stack/#{stack_id}/deploy"
    reports_urls(job_ids)
  end

  def reserve_handler
    stack_id = @args[2]
    response = post "/stack/#{stack_id}/reserve"
    puts response.inspect
  end

  def unreserve_handler
    stack_id = @args[2]
    response = post "/stack/#{stack_id}/unreserve"
    puts response.inspect
  end

  def change_stack_template_handler
    stack_id, template_id = @args[2], @args[3]
    r = inspect_parameters(@options_parser.delete_params, stack_id, template_id)
    unless r.nil?
      @options_parser.invalid_change_stack_template_command
      abort(r)
    end
    @show = put("/stack/#{stack_id}/stack_template", {stack_template: template_id})
  end

  private

  def provider_stacks(provider)
    if Providers.has_functionality?(provider, :stacks)
      get("/stacks/provider/#{provider}")
    else
      @options_parser.invalid_list_command
      abort()
    end
  end

end
