#pragma once

#include "merger.h"

namespace NRTYMerger {

    class IHeader {
    public:
        typedef TAtomicSharedPtr<IHeader> TPtr;
        virtual ~IHeader() {}
        virtual void Merge(IHeader* header) = 0;
        virtual void SerializeForMerger(IOutputStream& os, ui32 docsCount) = 0;
        virtual void DeserializeForMerger(IInputStream& os) = 0;
    };

    class IObject {
    public:
        typedef TAtomicSharedPtr<IObject> TPtr;
        virtual ~IObject() {}
        virtual void SerializeForMerger(NRTYMerger::IHeader* from, NRTYMerger::IHeader* to, IOutputStream& os) = 0;
        virtual void DeserializeForMerger(IInputStream& os) = 0;
    };

    class ISourceReader {
    public:
        typedef TAtomicSharedPtr<ISourceReader> TPtr;

        virtual ~ISourceReader() {}

        virtual IHeader::TPtr ReadHeader() = 0;
        virtual IObject::TPtr ReadObject(ui64 position) = 0;
    };

    class IDestWriter {
    public:

        typedef TAtomicSharedPtr<IDestWriter> TPtr;

        virtual ~IDestWriter() {}

        virtual bool AddHeader(IHeader* header) = 0;
        virtual bool WriteHeader(ui32 docsCount) = 0;
        virtual bool WriteObject(IHeader::TPtr& header, IObject::TPtr& object) = 0;
        virtual bool Finish() {
            return true;
        };
    };

    struct TContext {
        const std::atomic<bool>* StopFlag = nullptr;
    };

    class TBlockMerger {
    public:
        typedef TVector<ISourceReader::TPtr> TSourceReaders;
        typedef TVector<IDestWriter::TPtr> TDestWriters;

    private:
        TSourceReaders Sources;
        TDestWriters Dests;
        const TRTYMerger::IRTYMergerDocIdDecoder& Decoder;
    public:
        TBlockMerger(const TSourceReaders& sources, const TDestWriters& dests, const TRTYMerger::IRTYMergerDocIdDecoder& decoder)
            : Sources(sources)
            , Dests(dests)
            , Decoder(decoder)
        {

        }

        bool Merge(TContext& context);
    };
};
