#pragma once

#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/slots_pool.h>
#include <saas/library/sharding/sharding.h>
#include <library/cpp/json/writer/json_value.h>

#define AGGREGATE_ACTION_NAME "AGGREGATE_ACTION"

namespace NRTYDeploy {

    class TAggregateAction: public NDaemonController::TAction {
    private:
        TVector<TString> Pools;
        NSearchMapParser::TSlotsPool ResultPool;
    protected:

        virtual TString ActionName() const {
            return AGGREGATE_ACTION_NAME;
        }

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

        static TFactory::TRegistrator<TAggregateAction> Registrator;

        virtual TString GetCustomUri() const {
            return "";
        }

    public:

        TAggregateAction() {}

        TAggregateAction(const TVector<TString>& pools)
        {
            Pools = pools;
            Status = NDaemonController::TAction::asInProgress;
        }

        virtual bool IsLogicAction() const {
            return true;
        }

        virtual void DoInterpretResult(const TString& /*result*/) {
            if (!IsFinished())
                Fail("Not ready task for aggregation");
        }

        virtual void AddPrevActionsResult(const NRTYScript::ITasksInfo& info) {
            ui32 countIncorrectPath = 0;
            for (auto&& i : Pools) {
                if (i.StartsWith('$')) {
                    TString path = i.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
                            i = pool.Serialize().GetStringRobust();
                    } else {
                        DEBUG_LOG << "Incorrect extract data path " << path << Endl;
                        ++countIncorrectPath;
                    }
                }
            }
            if (!countIncorrectPath && !ResultPool.Size() && Status == NDaemonController::TAction::asInProgress) {
                for (auto&& i : Pools) {
                    NSearchMapParser::TSlotsPool pool;
                    if (!pool.DeserializeFromString(i)) {
                        Fail("Incorrect task info: can't deserialize: " + i);
                        return;
                    }
                    for (auto&& slot : pool.GetSlots()) {
                        ResultPool.Add(slot);
                    }
                }
                Success("");
            }
        }

        virtual TString DoBuildCommand() const {
            FAIL_LOG("Can't use this method");
            return "";
        }
    };
}
