#pragma once

#include <saas/rtyserver/components/oxy/abstract/merger.h>
#include <saas/util/queue.h>

#include <search/panther/indexing/counts_to_panther/batch_processor.h>
#include <search/panther/indexing/counts_to_panther/operations.h>
#include <kernel/doom/yandex/yandex_writer.h>

namespace NRTYServer {
    template <class TTermProcessor>
    class TPantherHitsProcessor {
        using TContext = NPanther::TTermContext;
        using TWriter = NDoom::TYandexWriter<NDoom::TPantherHit>;
        using TProcessAndWriteJob = NPanther::TProcessAndWriteTermFunction<TTermProcessor, TWriter>;

        static constexpr ui32 WriterVersion_ =
            YNDEX_VERSION_BLK8 +
            YNDEX_VERSION_FLAG_KEY_ADDITIONALY_COMPRESSED_YAPPY +
            YNDEX_VERSION_FLAG_KEY_2K;

    public:
        inline TPantherHitsProcessor(const TString& destination, TTermProcessor& processor, const NPanther::TCountsToPantherOptions& options)
            : TermProcessor_(processor)
            , Writer_(destination, WriterVersion_)
            , ProcessAndWriteJob_(TermProcessor_, Writer_, options)
            , BatchProcessor_(ProcessAndWriteJob_, 1024,
                CreateRTYQueue(1, 0, NUtil::TSmartMtpQueue::TOptions::GetNoBallocOptions().SetThreadName("PantherHitsProc"))
            )
        {
        }

        ~TPantherHitsProcessor() {
            if (!Context_.Hits.empty()) {
                BatchProcessor_.Add(std::move(Context_));
            }
            BatchProcessor_.Stop();
        }

        inline void SetKey(const char* key) {
            if (!Context_.Hits.empty()) {
                BatchProcessor_.Add(std::move(Context_));
                Context_ = TContext();
            }
            TermProcessor_.InitTerm(Context_, key);
        }

        inline void AddHit(SUPERLONG hit, ui32 /*cluster*/) {
            if (!Context_.IsSkipped) {
                Context_.Hits.push_back(NDoom::TCountsHit::FromSuperLong(hit));
            }
        }

    private:
        TTermProcessor& TermProcessor_;
        TWriter Writer_;
        TProcessAndWriteJob ProcessAndWriteJob_;
        TBatchProcessor<TProcessAndWriteJob, TContext> BatchProcessor_;

        // local temporary variables
        TContext Context_;
    };
}

class TOxygenCountsAndPantherMerger : public IOxyMerger {
public:
    virtual bool DoMerge(const NRTYServer::TMergeContext& context, const TRTYServerConfig& config) override;
    virtual bool DoInitialize() override;
private:
    static TFactory::TRegistrator<TOxygenCountsAndPantherMerger> Registrator;
};
