#pragma once

#include <saas/deploy_manager/scripts/cluster/cluster_task.h>
#include <saas/library/daemon_base/actions_engine/controller_client.h>
#include <saas/library/searchmap/searchmap.h>
#include <saas/library/searchmap/slots_pool.h>
#include <saas/library/sharding/sharding.h>
#include <util/string/vector.h>

#define MODIF_SEARCHMAP_ACTION_NAME "MODIF_SEARCHMAP"

namespace NDaemonController {

    class TSimpleSearchmapModifAction : public NRTYDeploy::TClusterAsyncAction {
    private:
        TString Slots;
        TString CType;
        TString Service;
        TString Action;
        TString ResultSearchmap;
        TString ServiceType;
        TString ServiceInfo;
        TString NewServiceName;
        TMap<TString, TString> RepalceIntervalsMap;
        bool AddToSearchMap = false;
        bool Deploy = true;
        bool DeployProxies = 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 "modify_searchmap";
        }

        virtual TString DoBuildCommandStart() const override {
            TString intervals;
            for (const auto& i : RepalceIntervalsMap) {
                intervals += "&interval=" + i.first + "->" + i.second;
            }
            return "slots=" + Slots +
                   "&service_type=" + ServiceType +
                   "&ctype=" + CType +
                   "&service=" + Service +
                   "&action=" + Action +
                   "&deploy=" + ToString(Deploy) +
                   "&service_info=" + ServiceInfo +
                   "&deploy_proxies=" + ToString(DeployProxies) +
                   "&new_service_name=" + NewServiceName +
                   "&add_to_search_map=" + ToString(AddToSearchMap) +
                   "&may_be_dead_procentage=" + ToString(MayBeDeadIntervalPercentage) +
                   intervals;

        }

        void AddPrevActionsResult(const NRTYScript::ITasksInfo& info) override {
            if (Slots.StartsWith('$')) {
                TString path = Slots.substr(1);
                NJson::TJsonValue result;
                if (info.GetValueByPath(path, result) && !!result.GetStringRobust()) {
                    NSearchMapParser::TSlotsPool pool;
                    if (!pool.DeserializeFromString(result.GetStringRobust()))
                        Fail("Incorrect task info: " + result.GetStringRobust() + " / " + path);
                    else
                        Slots = pool.Serialize().GetStringRobust();
                } else {
                    DEBUG_LOG << "Incorrect extract data path " << path << Endl;
                }
            }
        }

        virtual void DoInterpretResult(const TString& result) override;

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

        TSimpleSearchmapModifAction() {}

        TSimpleSearchmapModifAction(const NSearchMapParser::TSlotsPool& slots, const TString& ctype, const TString& service, const TString& action, const TString& serviceType,
            bool deploy = false, bool deployProxies = true, float mayBeDeadIntervalPercentage = 0.01f
        )
            : TClusterAsyncAction(apStartAndWait)
            , Slots(slots.Serialize().GetStringRobust())
            , CType(ctype)
            , Service(service)
            , Action(action)
            , ServiceType(serviceType)
            , Deploy(deploy)
            , DeployProxies(deployProxies)
            , MayBeDeadIntervalPercentage(mayBeDeadIntervalPercentage)
        {}

        TSimpleSearchmapModifAction(const TString& slotsAddress, const TString& ctype, const TString& service, const TString& action, const TString& serviceType,
            bool deploy = false, bool deployProxies = true, float mayBeDeadIntervalPercentage = 0.01f
        )
            : TClusterAsyncAction(apStartAndWait)
            , Slots(slotsAddress)
            , CType(ctype)
            , Service(service)
            , Action(action)
            , ServiceType(serviceType)
            , Deploy(deploy)
            , DeployProxies(deployProxies)
            , MayBeDeadIntervalPercentage(mayBeDeadIntervalPercentage)
        {}

        TSimpleSearchmapModifAction(const TVector<TString>& slots, const TString& ctype, const TString& service, const TString& action, const TString& serviceType,
            bool deploy = false, bool deployProxies = true, float mayBeDeadIntervalPercentage = 0.01f
        )
            : CType(ctype)
            , Service(service)
            , Action(action)
            , ServiceType(serviceType)
            , Deploy(deploy)
            , DeployProxies(deployProxies)
            , MayBeDeadIntervalPercentage(mayBeDeadIntervalPercentage)
        {
            NSearchMapParser::TSlotsPool slotsPool;
            CHECK_WITH_LOG(Action != "add");
            slotsPool.Parse(slots);
            Slots = slotsPool.Serialize().GetStringRobust();
        }

            TSimpleSearchmapModifAction(const TString& ctype, const TString& service, const TString& action, const TString& serviceType, const bool addToSearchMap, const TString& newServiceName,
                bool deploy = false, bool deployProxies = true, float mayBeDeadIntervalPercentage = 0.01f
            )
            : CType(ctype)
            , Service(service)
            , Action(action)
            , ServiceType(serviceType)
            , NewServiceName(newServiceName)
            , AddToSearchMap(addToSearchMap)
            , Deploy(deploy)
            , DeployProxies(deployProxies)
            , MayBeDeadIntervalPercentage(mayBeDeadIntervalPercentage)
        {
        }

        TSimpleSearchmapModifAction(const NSearchMapParser::TServiceSpecificOptions& serviceInfo, const TString& ctype, const TString& service, const TString& serviceType, bool deploy = false);
        TSimpleSearchmapModifAction(const TString& serviceInfo, const TString& ctype, const TString& service, const TString& serviceType, bool deploy = false);

        void ReplaceInterval(const NSearchMapParser::TShardsInterval& from, const NSearchMapParser::TShardsInterval& to) {
            RepalceIntervalsMap[from.ToString()] = to.ToString();
        }

        virtual bool GetNotContinuableTaskOnStarting() const override {
            return false;
        }

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