#pragma once

#include "merger.h"

#include <kernel/walrus/finalremaptable.h>

extern const char* INDEX_SUFFIX;

class TMergeDocInfos {
public:
    class TDocInfoSource {
        const TMergeDocInfos& Records;
        mutable TRTYMerger::TAddress CurrentNewAddress;
        mutable TRTYMerger::TAddress CurrentOldAddress;
        mutable bool Valid;
    public:
        explicit TDocInfoSource(const TMergeDocInfos& docInfos)
            : Records(docInfos)
        {
            Restart();
        }

        void Next() const {
            if (!IsValid())
                return;
            if (++CurrentNewAddress.DocId >= Records.Decoder->GetNewDocsCount(CurrentNewAddress.ClusterId)) {
                ++CurrentNewAddress.ClusterId;
                CurrentNewAddress.DocId = 0;
            }
            Valid = Records.Decoder->NewToOld(CurrentNewAddress.ClusterId, CurrentNewAddress.DocId, CurrentOldAddress);
        }

        bool IsValid() const {
            return Valid;
        }

        void Restart() {
            CurrentNewAddress = TRTYMerger::TAddress(0, 0);
            Valid = Records.Decoder->NewToOld(CurrentNewAddress.ClusterId, CurrentNewAddress.DocId, CurrentOldAddress);
        }

        ui32 GetFromCl() const {
            Y_ASSERT(IsValid());
            return CurrentOldAddress.ClusterId;
        }
        ui32 GetFromDocId() const {
            Y_ASSERT(IsValid());
            return CurrentOldAddress.DocId;
        }
        ui32 GetToCl() const {
            Y_ASSERT(IsValid());
            return CurrentNewAddress.ClusterId;
        }
        ui32 GetToDocId() const {
            Y_ASSERT(IsValid());
            return CurrentNewAddress.DocId;
        }
    };

private:
    TRTYMerger::IRTYMergerDocIdDecoder* Decoder;
    TRTYMerger::IRTYMergerDocIdInfo* Info;
    size_t ClustersCount;

public:
    TRTYMerger::IRTYMergerDocIdDecoder* GetDecoder() {
        return Decoder;
    }

    const TRTYMerger::IRTYMergerDocIdInfo* GetDocsInfo() const {
        return Info;
    }

    TDocInfoSource GetIterator() {
        return TDocInfoSource(*this);
    }

    TMergeDocInfos(size_t clustersNumber, TRTYMerger::IRTYMergerDocIdDecoder* decoder, TRTYMerger::IRTYMergerDocIdInfo* info)
        : Decoder(decoder)
        , Info(info)
        , ClustersCount(clustersNumber)
    {
        Y_VERIFY(Decoder);
    }

    void GenerateFinalRemapTable(TFinalRemapTable& table) {
        table.Create(ClustersCount, TFinalRemapTable::DELETED_DOCUMENT);
        for (TDocInfoSource dis = GetIterator(); dis.IsValid(); dis.Next()) {
            table.SetRemapItem(dis.GetFromCl(), dis.GetFromDocId(), dis.GetToCl(), dis.GetToDocId());
        }
    }

    bool IsEmpty() const {
        return Decoder->GetNewDocsCount() == 0;
    }
};

