require "lib/executors/server_executor"
require "commands/status"
require "workers/deploy_worker"
require "exceptions/deploy_info_error"
require "app/api3/parsers/deploy"
require_relative "request_handler"

module Devops
  module API3
    module Handler
      class Deploy < RequestHandler
#        extend DeployCommands
        extend StatusCommands

        set_parser Devops::API3::Parser::DeployParser

        def deploy
          body = parser.deploy
          names = body["names"]
          tags = body["tags"] || []
          run_list = body["run_list"]
          files = []
          jid = nil
          owner = parser.current_user
          @deploy_info_buf = {}
          servers(names).each do |s|
            project = begin
              Devops::Model::Project.check_user_authorization(s.project, s.environment, owner)
            rescue InvalidPrivileges, RecordNotFound  => e
              DevopsLogger.logger.warn e.message
              next
            end
            begin
              deploy_info = create_deploy_info(s, project, body["build_number"])
              deploy_info["run_list"] = run_list if run_list
              deploy_info["named_task"] = body["named_task"]

              jid = Worker.start_async(DeployWorker,
                server_attrs: s.to_hash,
                owner: owner,
                tags: tags,
                deploy_info: deploy_info
              )

            rescue DeployInfoError => e
              msg = "Can not get deploy info: " + e.message
              DevopsLogger.logger.error msg
              jid = "error_#{s.name}_#{Time.new.to_i}"
              file = File.jon(dir, jid)
              File.open(file, "w") do |out|
                out.write msg
              end
              o = {
                "file" => file,
                "_id" => jid,
                "created_by" => owner,
                "project" => s.project,
                "environment" => s.environment,
                "type" => JobTask::DEPLOY_TYPE,
                "status" => Worker::STATUS::FAILED
#                "attributes" => attributes
              }
              JobTask.create(o)
            end
            files.push(jid)
          end
          files
        end

        def deploy_stream out
          body = parser.deploy
          names = body["names"]
          tags = body["tags"] || []
          run_list = body["run_list"]
          status = []
          owner = parser.current_user
          @deploy_info_buf = {}
          servers(names).each do |s|
            project = begin
              Devops::Model::Project.check_user_authorization(s.project, s.environment, owner)
            rescue InvalidPrivileges, Devops::Exception::RecordNotFound  => e
              out << e.message + "\n"
              status.push 2
              next
            end
            begin
              deploy_info = create_deploy_info(s, project, body["build_number"])
              deploy_info["run_list"] = run_list if run_list
              res = Devops::Executor::ServerExecutor.new(s, out, current_user: owner).deploy_server_with_tags(tags, deploy_info)
              status.push(res)
            rescue DeployInfoError => e
              msg = "Can not get deploy info: " + e.message
              DevopsLogger.logger.error msg
              out << msg + "\n"
              status.push 2
              next
            end
          end
          status
        rescue Devops::Exception::RecordNotFound  => e
          out << e.message
          [-10]
        end

        def servers names
          servers = Devops::Model::Server.find(name: {'$in' => names}, reserved: true)
          raise Devops::Exception::RecordNotFound.new("No reserved servers found for names '#{names.join("', '")}'") if servers.empty?
          servers.sort_by!{|s| names.index(s.name)}
          servers
        end

        def create_deploy_info server, project, build_number
          deploy_env_model = project.environment(server.environment)
          buf_key = "#{server.project}_#{server.environment}"
          deploy_info = if @deploy_info_buf.key?(buf_key)
            @deploy_info_buf[buf_key]
          else
            @deploy_info_buf[buf_key] = project.deploy_info(deploy_env_model, build_number)
          end
        end

      end
    end
  end
end

