#pragma once

#include <saas/library/daemon_base/controller_actions/async_controller_action.h>
#include <saas/library/sharding/sharding.h>
#include <util/string/vector.h>

#define SYNC_DETACH_ACTION_NAME "SYNC_DETACH"

namespace NDaemonController {

    class TDetachAction : public TControllerAsyncAction {
    private:
        TVector<NSearchMapParser::TShardIndex> ShardMin;
        TVector<NSearchMapParser::TShardIndex> ShardMax;
        NSaas::TShardsDispatcher::TContext Sharding;
        TVector<TString> IdRes;
    protected:

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

        virtual NJson::TJsonValue DoSerializeToJson() const override ;
        virtual void DoDeserializeFromJson(const NJson::TJsonValue& json) override ;
        virtual void InterpretTaskReply(TAsyncTaskExecutor::TTask::TStatus taskStatus, const NJson::TJsonValue& result) override;

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

        TDetachAction()
            : TControllerAsyncAction(NDaemonController::apStartAndWait)
            , Sharding(NSaas::UrlHash)
        {}

        TDetachAction(NSearchMapParser::TShardIndex shardMin, NSearchMapParser::TShardIndex shardMax, const NSaas::TShardsDispatcher::TContext& sharding, TAsyncPolicy asyncPolicy)
            : TControllerAsyncAction(asyncPolicy)
            , Sharding(sharding)
        {
            ShardMin = TVector<NSearchMapParser::TShardIndex>(1, shardMin);
            ShardMax = TVector<NSearchMapParser::TShardIndex>(1, shardMax);
        }

        TDetachAction(NSearchMapParser::TShardIndex shardMin, NSearchMapParser::TShardIndex shardMax, const TString& waitTask)
            : TControllerAsyncAction(waitTask)
            , Sharding(NSaas::UrlHash)
        {
            ShardMin = TVector<NSearchMapParser::TShardIndex>(1, shardMin);
            ShardMax = TVector<NSearchMapParser::TShardIndex>(1, shardMax);
        }

        TDetachAction(TVector<NSearchMapParser::TShardsInterval> intervals, const TString& waitTask)
            : TControllerAsyncAction(waitTask)
            , Sharding(NSaas::UrlHash)
        {
            for (ui32 i = 0; i < intervals.size(); ++i) {
                ShardMin.push_back(intervals[i].GetMin());
                ShardMax.push_back(intervals[i].GetMax());
            }
        }

        TDetachAction(const TVector<NSearchMapParser::TShardIndex>& shardMin, const TVector<NSearchMapParser::TShardIndex>& shardMax, const NSaas::TShardsDispatcher::TContext& sharding, TAsyncPolicy asyncPolicy)
            : TControllerAsyncAction(asyncPolicy)
            , Sharding(sharding)
        {
            CHECK_WITH_LOG(shardMin.size() == shardMax.size());
            ShardMin = shardMin;
            ShardMax = shardMax;
        }

        TDetachAction(TVector<NSearchMapParser::TShardsInterval> intervals, const NSaas::TShardsDispatcher::TContext& sharding, TAsyncPolicy asyncPolicy)
            : TControllerAsyncAction(asyncPolicy)
            , Sharding(sharding)
        {
            for (ui32 i = 0; i < intervals.size(); ++i) {
                ShardMin.push_back(intervals[i].GetMin());
                ShardMax.push_back(intervals[i].GetMax());
            }
        }

        TDetachAction(const TVector<NSearchMapParser::TShardIndex>& shardMin, const TVector<NSearchMapParser::TShardIndex>& shardMax, const TString& waitTask)
            : TControllerAsyncAction(waitTask)
            , Sharding(NSaas::UrlHash)
        {
            CHECK_WITH_LOG(shardMin.size() == shardMax.size());
            ShardMin = shardMin;
            ShardMax = shardMax;
        }

        virtual TLockType GetLockType() const override {
            return ltReadLock;
        }

        TVector<TString> GetResults() const {
            return IdRes;
        }

        virtual TString DoBuildCommandStart() const override {
            CHECK_WITH_LOG(!WaitActionName);
            TString smin;
            TString smax;
            for (ui32 i = 0; i < ShardMin.size(); ++i) {
                smin += ToString(ShardMin[i]) + ",";
                smax += ToString(ShardMax[i]) + ",";
            }
            return "command=synchronizer&async=yes&action=detach&min_shard=" + smin + "&max_shard=" + smax + "&sharding_type=" + Sharding.ToString();
        }

        virtual TDuration GetWaitTimeoutDuration() const override {
            return TDuration::Days(30);
        }

    };
}
