#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_REPLICA_ACTION_NAME "ADD_REPLICA"

namespace NDaemonController {

    class TAddReplicaAction : public NRTYDeploy::TClusterAsyncAction {
    private:
        ui32 SlotsCount = 0;
        TString Service;
        TString CType;
        NRTYCluster::TSlotsAllocator SlotsAllocator;
        ui32 CountReplicas = 0;
        TString ServiceType;
        NSearchMapParser::TSlotsPool Pool;
        bool Restore = false;
        bool AllocateOnly = false;
        bool DeployProxy = false;
        float MayBeDeadIntervalPercentage = 0.01f;
    protected:

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

        virtual TString GetCustomUriStart() const override {
            return "add_replica";
        }

        virtual TString DoBuildCommandStart() const override {
            return "slots_count=" + ToString(SlotsCount) +
                   "&ctype=" + CType +
                   "&service=" + Service +
                   "&slots_allocator=" + SlotsAllocator.SerializeToJson().GetStringRobust() +
                   "&replicas_count=" + ToString(CountReplicas) +
                   "&service_type=" + ServiceType +
                   "&restore=" + ToString(Restore) +
                   "&allocate_only=" + ToString(AllocateOnly) +
                   "&deploy_proxy=" + ToString(DeployProxy) +
                   "&may_be_dead_procentage=" + ToString(MayBeDeadIntervalPercentage)
                   ;
        }

        virtual void DoInterpretResultWait(const TString& result) override {
            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()) {
                const NJson::TJsonValue& tasks = valueJson["script"]["graph"]["vertices"];
                VERIFY_WITH_LOG(tasks.IsArray(), "Incorrect data: %s", result.data());
                CHECK_WITH_LOG(tasks.GetArray().size() > 0);
                const NJson::TJsonValue& allocatorInfo = tasks[0]["task"]["action"]["task"]["allocator"];
                VERIFY_WITH_LOG(allocatorInfo.IsMap(), "Incorrect data: %s", result.data());
                const NJson::TJsonValue& resultPool = tasks[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<TAddReplicaAction> Registrator;
    public:

        TAddReplicaAction() {}

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

        TAddReplicaAction(ui32 slotsCount, TString service, TString cType, ui32 countReplicas, const NRTYCluster::TSlotsAllocator& slotsAllocator,
            TAsyncPolicy policy, const TString& serviceType,
            bool restore, bool allocateOnly = false, bool deployProxy = true, float mayBeDeadIntervalPercentage = 0.01f
        )
            : TClusterAsyncAction(policy)
            , SlotsCount(slotsCount)
            , Service(service)
            , CType(cType)
            , SlotsAllocator(slotsAllocator)
            , CountReplicas(countReplicas)
            , ServiceType(serviceType)
            , Restore(restore)
            , AllocateOnly(allocateOnly)
            , DeployProxy(deployProxy)
            , MayBeDeadIntervalPercentage(mayBeDeadIntervalPercentage)
        {
        }

        virtual TString ActionName() const override { return ADD_REPLICA_ACTION_NAME; }

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

    };
}
