#pragma once

#include "task.h"
#include <saas/deploy_manager/scripts/cluster/cluster_task.h>
#include <saas/library/daemon_base/actions_engine/controller_client.h>
#include <saas/library/daemon_base/actions_engine/controller_script.h>
#include <saas/library/searchmap/searchmap.h>
#include <saas/library/searchmap/slots_pool.h>
#include <saas/library/sharding/sharding.h>
#include <library/cpp/json/writer/json_value.h>

#define RESTORE_ACTION_NAME "RESTORE_INDEX_ACTION"

namespace NRTYDeploy {

    class TRestoreIndexAction: public NRTYDeploy::TClusterAsyncAction {
    private:
        TString Service;
        TString CType;
        TString RestoreSlots;
        TSet<TString> NotUsefulSlots;
    protected:

        virtual TString ActionName() const {
            return RESTORE_ACTION_NAME;
        }

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

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

        TRestoreIndexAction() {}

        TRestoreIndexAction(const TString& service, const TString& ctype, const TSet<TString>& notUsefulSlots,
            const TString& restoreSlots, NDaemonController::TAsyncPolicy aPolicy)
            : TClusterAsyncAction(aPolicy)
        {
            Service = service;
            CType = ctype;
            RestoreSlots = restoreSlots;
            NotUsefulSlots = notUsefulSlots;
        }

        virtual void AddPrevActionsResult(const NRTYScript::ITasksInfo& info) {
            if (RestoreSlots.StartsWith('$')) {
                TString path = RestoreSlots.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 {
                        RestoreSlots = pool.Serialize().GetStringRobust();
                        for (const auto& slot : pool.GetSlots())
                            NotUsefulSlots.insert(slot.GetShortSlotName());
                    }
                }
                else {
                    DEBUG_LOG << "Incorrect extract data path " << path << Endl;
                }
            }
        }

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

        virtual TString DoBuildCommandStart() const {
            return "service=" + Service +
                "&ctype=" + CType +
                "&not_useful_slots=" + JoinStrings(NotUsefulSlots.cbegin(), NotUsefulSlots.cend(), ",") +
                "&restore_slots=" + RestoreSlots;
        }
    };
}
