#include "sync_processor.h"
#include "synchronizer.h"
#include "config.h"

#include <saas/rtyserver/synchronizer/library/resource.h>
#include <saas/rtyserver/synchronizer/library/sync.h>

#include <saas/rtyserver/config/realm_config.h>

#include <util/string/subst.h>

namespace {
    class TSyncResourceFetchCallback : public NRTYServer::IRemoteResourceGetCallback {
    private:
        TAsyncTaskExecutor::TTask& Task;

    public:
        TSyncResourceFetchCallback(TAsyncTaskExecutor::TTask& task)
            : Task(task)
        { }

        void OnSkyGetStart(ui32 /*retryNum*/) final {
            (*Task.GetReply())["sky_progress"].AppendValue(NJson::TJsonValue());
        }

        void OnSkyGetError(const TString& errorInfo) final {
            (*Task.GetReply())["sky_progress"].Back().InsertValue("error", errorInfo);
        }

        void OnSkyStart(const TString& commandLine) final {
            (*Task.GetReply())["sky_progress"].Back().InsertValue("command-line", commandLine);
        }
    };
}

namespace NRTYServer {

    TSyncProcessor::TSyncProcessor(TSynchronizer* synchronizer)
        : ISynchronizerProcessor(synchronizer)
    {}

    bool TSyncProcessor::ProcessRequest(const TCgiParameters& cgi, TStringBuf postBuffer, TAsyncTaskExecutor::TTask& task) {
        Y_UNUSED(postBuffer);
        DEBUG_LOG << "Start sync request processing " << cgi.Print() << Endl;
        const TString& idResource = cgi.Get("id_res");
        if (!idResource)
            ythrow yexception() << "TSyncProcessor: there is no id_res";
        task.GetReply()->InsertValue("id_res", idResource);
        if (idResource == "EMPTY")
            return true;

        NRTYServer::EConsumeMode consumeMode = NRTYServer::EConsumeMode::Append;
        if (cgi.Has("consume_mode")) {
            if (!TryFromString(cgi.Get("consume_mode"), consumeMode)) {
                ythrow yexception() << "TSyncProcessor: cannot parse consume_mode: " << cgi.Get("consume_mode").Quote();
            }
        }

        NRTYServer::TRemoteResource resource(idResource);
        TString name("sync-" + idResource);
        SubstGlobal(name, "/", "_");
        resource.SetName(name);

        TSyncResourceFetchCallback callback(task);
        const TString& indexDir = Synchronizer->GetRTYConfig().GetRealmListConfig().GetMainRealmConfig().RealmDirectory;
        const NRTYServer::TResourceFetchConfig* fetchConfigPtr = &Synchronizer->GetRTYConfig().GlobalResourceFetchConfig;
        if (Synchronizer->GetConfig() && Synchronizer->GetConfig()->ResourceFetchConfig) {
            fetchConfigPtr = Synchronizer->GetConfig()->ResourceFetchConfig.Get();
        }
        if (NRTYServer::FetchAndConsumeIndices(resource, consumeMode, indexDir, *fetchConfigPtr, &callback)) {
            INFO_LOG << "Successful FetchAndConsumeIndices, removing persistent search ban if any" << Endl;
            TCgiParameters cgi2("action=slot_info&subaction=remove_persistent_search_ban");
            TMessageSynchronizerCall message(cgi2, "", task);
            SendGlobalMessage(message);
        } else {
            WARNING_LOG << "Error in FetchAndConsumeIndices while processing sync request";
        }
        DEBUG_LOG << "Finish sync request processing " << cgi.Print() << Endl;
        return true;
    }
}
