#pragma once

#include <saas/deploy_manager/scripts/cluster/cluster_task.h>
#include <saas/deploy_manager/scripts/common/slots_allocator/allocator.h>

#include <util/string/vector.h>

#define ADD_INTSEARCH_ACTION_NAME "ADD_INTSEARCH"

namespace NRTYDeploy {

    class TAddIntSearchAction : public NRTYDeploy::TClusterAsyncAction {
    private:
        TString Service;
        TString CType;
        ui32 CountReplicas;
        ui32 CountShards;
        NRTYCluster::TSlotsAllocator SlotsAllocator;
        NSearchMapParser::TSlotsPool Pool;
    protected:

        virtual NJson::TJsonValue DoSerializeToJson() const;
        virtual void DoDeserializeFromJson(const NJson::TJsonValue& json);

        virtual TString GetCustomUriStart() const {
            return "add_intsearch";
        }

        virtual TString DoBuildCommandStart() const {
            return "&ctype=" + CType +
                   "&service=" + Service +
                   "&count_replicas=" + ToString(CountReplicas) +
                   "&count_shards=" + ToString(CountShards) +
                   "&slots_allocator=" + SlotsAllocator.SerializeToJson().GetStringRobust()
                   ;
        }

        virtual void DoInterpretResultWait(const TString& result) {
            NJson::TJsonValue valueJson;
            VERIFY_WITH_LOG(NJson::ReadJsonFastTree(result, &valueJson), "Incorrect data: %s", result.data());
            VERIFY_WITH_LOG(valueJson.Has("is_finished"), "Incorrect data: %s", result.data());
            if (!Pool.Size() && valueJson["is_finished"].GetBoolean()) {
                NJson::TJsonValue tasks = valueJson["script"]["graph"]["vertices"];
                NJson::TJsonValue::TArray arr;
                VERIFY_WITH_LOG(tasks.GetArray(&arr), "Incorrect data: %s", result.data());
                CHECK_WITH_LOG(arr.size() > 0);
                NJson::TJsonValue allocatorInfo = arr[0]["task"]["action"]["task"]["allocator"];
                VERIFY_WITH_LOG(allocatorInfo.IsMap(), "Incorrect data: %s", result.data());
                NJson::TJsonValue resultPool = arr[0]["task"]["action"]["task"]["result_pool"];
                if (resultPool.IsArray()) {
                    VERIFY_WITH_LOG(Pool.DeserializeFromJson(resultPool), "Incorrect data: %s", resultPool.GetStringRobust().data());
                }
            }
            NRTYDeploy::TClusterAsyncAction::DoInterpretResultWait(result);
        }

        static TFactory::TRegistrator<TAddIntSearchAction> Registrator;
    public:

        TAddIntSearchAction() {}

        TAddIntSearchAction(const TString& waitActionName)
            : TClusterAsyncAction(waitActionName)
        {}

        TAddIntSearchAction(TString service, TString cType, NDaemonController::TAsyncPolicy policy, ui32 countShards, ui32 countReplicas, const NRTYCluster::TSlotsAllocator& slotsAllocator)
            : TClusterAsyncAction(policy)
            , Service(service)
            , CType(cType)
            , CountReplicas(countReplicas)
            , CountShards(countShards)
            , SlotsAllocator(slotsAllocator)
        {}

        virtual TString ActionName() const { return ADD_INTSEARCH_ACTION_NAME; }

        const NSearchMapParser::TSlotsPool& GetPool() const {
            return Pool;
        }

    };
}
