#include "merger.h"
#include "interface.h"

#include <saas/rtyserver/model/component.h>
#include <kernel/doom/yandex/sequential_yandex_reader.h>

#include <robot/library/oxygen/indexer/processor/protos/config.pb.h>

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

#include <saas/rtyserver/merger/library/merger.h>
#include <saas/rtyserver/merger/library/doc_infos.h>

#include <kernel/walrus/advmerger.h>

#include <library/cpp/mediator/global_notifications/system_status.h>

bool TOxygenCountsAndPantherMerger::DoMerge(const NRTYServer::TMergeContext& mergeContext, const TRTYServerConfig& config) {
    const TRTYMerger::TContext& context = mergeContext.Context;
    const NOxygen::TOxygenOptions* oxygenOptions = config.GetRealmListConfig().GetRealmConfigByConfigName(mergeContext.RealmName).GetOxygenOptions();
    AssertCorrectConfig(oxygenOptions, "OxygenOptions are missing");
    CHECK_WITH_LOG(oxygenOptions->GetRTYProcessorOptions().HasPantherOptions());
    const NOxygen::TCountsToPantherOptions& countsToPantherOptions = oxygenOptions->GetRTYProcessorOptions().GetPantherOptions().GetCountsToPantherOptions();

    NPanther::TCountsToPantherOptions options;
    NRTYServer::IPantherImplementation::ConvertPantherOptions(countsToPantherOptions, options);
    options.SortOutHits = true;

    THolder<NRTYServer::IPantherImplementation> Implementation(NRTYServer::IPantherImplementation::TFactory::Construct(options.Version));
    AssertCorrectConfig(!!Implementation, "missing Panther implementation");

    TSimpleSharedPtr<TAdvancedMergeTask> task(new TAdvancedMergeTask());
    task->TmpFileDir = context.TempDir;


    THashSet<TString> frequentKeys;
    for (size_t i = 0; i < context.Sources.size(); ++i) {
        const TString& processedPath = context.Sources[i] + ::INDEX_SUFFIX + "counts.";
        task->Inputs.push_back(TAdvancedMergeTask::TMergeInput(processedPath));

        INFO_LOG << "Calculating FrequentKeys for " << processedPath << Endl;
        const size_t minUnigramDocs = (context.Decoder->GetSizeOfCluster(i) + 1) / countsToPantherOptions.GetMaxUnigramIdf();
        NDoom::TSequentialYandexReader<NDoom::TCountsHit> reader(processedPath);
        const auto& sourceFrequentKeys = NPanther::ReadFrequentKeys(
                reader, minUnigramDocs);
        INFO_LOG << "Merging FrequentKeys from " << processedPath << Endl;
        frequentKeys.insert(sourceFrequentKeys.begin(), sourceFrequentKeys.end());
        INFO_LOG << "Merged FrequentKeys from" << processedPath << Endl;
    }
    for (size_t i = 0; i < context.Dests.size(); ++i) {
        const TString& processedPath = context.Dests[i] + ::INDEX_SUFFIX + "counts.";
        task->Outputs.push_back(TAdvancedMergeTask::TMergeOutput(processedPath));
    }

    TMergeDocInfos infos(context.Sources.size(), context.Decoder, context.Info);
    infos.GenerateFinalRemapTable(task->FinalRemapTable);

    return Implementation->MergeCountsAndPanther(task, context, options, frequentKeys, mergeContext.RigidStopSignal);
}

bool TOxygenCountsAndPantherMerger::DoInitialize() {
    return true;
}

IOxyMerger::TFactory::TRegistrator<TOxygenCountsAndPantherMerger> TOxygenCountsAndPantherMerger::Registrator("TRTYPantherProcessor");
