#pragma once

#include <util/generic/string.h>
#include <util/generic/vector.h>
#include <util/generic/ylimits.h>
#include <util/system/types.h>

extern const ui32 REMAP_NOWHERE;

class IMergerCallback {
public:
    virtual ~IMergerCallback() {};
    virtual void OnAfterArcMerge() {};
    virtual void OnAfterKeyInvMerge() {};
    virtual void OnAfterGrAttrMerge() {};
    virtual void OnBeforeUpdatableMerging() {};
};

struct TRTYMergerAddress {
    ui32 ClusterId;
    ui32 DocId;

    inline TRTYMergerAddress()
        : ClusterId(0)
        , DocId(0)
    {}

    inline TRTYMergerAddress(ui32 clusterId, ui32 docId)
        : ClusterId(clusterId)
        , DocId(docId)
    {

    }

    inline bool operator < (const TRTYMergerAddress& a) const {
        if (ClusterId == a.ClusterId)
            return DocId < a.DocId;
        else
            return (ClusterId < a.ClusterId);
    }

    bool IsRemoved() const;
};

class IRTYMergerDocIdInfo {
private:
public:
    virtual ~IRTYMergerDocIdInfo() {}
    virtual ui64 Timestamp(ui32 clusterId, ui32 docId) const = 0;
};

class IRTYMergerDocIdDecoder {
public:
    virtual ~IRTYMergerDocIdDecoder() {}
    virtual TRTYMergerAddress Decode(ui32 clusterId, ui32 docId) const = 0;
    virtual bool Check(ui32 clusterId, ui32 docId) const = 0;
    virtual ui32 GetSizeOfCluster(ui32 clusterId) const = 0;
    virtual ui32 GetSize() const = 0;
    virtual bool IsValidClusterId(ui32 clusterId) const = 0;
    virtual ui32 GetNewDocsCount(ui32 clusterId = Max<ui32>()) const = 0;
    virtual bool NewToOld(ui32 clusterId, ui32 docId, TRTYMergerAddress& addr) const = 0;
    virtual void PatchDestMap(ui32 clusterId, const TVector<ui32>& remap) = 0;
};

//
// TRTYMergerContextBase class is the RTY analog to [kernel/walrus/advmerger.h] TAdvancedMergeTask
// The kernel/Walrus version is legacy and will be eventually wiped out.
//
struct TRTYMergerContextBase {
    TVector<TString> Sources;
    TVector<TString> Dests;
    TVector<TString> TmpfsDests;
    TString TempDir;
    IRTYMergerDocIdDecoder* Decoder;
    IRTYMergerDocIdInfo* Info;
    IMergerCallback* Callback;

    TRTYMergerContextBase(const TVector<TString>& sources, const TVector<TString>& dests, const TVector<TString>& tmpfsDest, TString tempDir,
            IRTYMergerDocIdDecoder* decoder, IRTYMergerDocIdInfo* info, IMergerCallback* callback = nullptr)
        : Sources(sources)
        , Dests(dests)
        , TmpfsDests(tmpfsDest)
        , TempDir(tempDir)
        , Decoder(decoder)
        , Info(info)
        , Callback(callback)
    {
    }
};

