#pragma once

#include "ki_actor.h"

#include <saas/library/mapping/mapping.h>

#include <kernel/index_mapping/index_mapping.h>
#include <ysite/yandex/srchmngr/yrequester.h>

#include <util/generic/ptr.h>
#include <util/generic/vector.h>

namespace NRTYServer {
    class TKIProcessorTraits {
    public:
        static inline TString GetIndexPrefix(const TString& name) {
            return "index." + name + ".";
        }
        static inline TString GetKeyFilename(const TString& name) {
            return GetIndexPrefix(name) + "key";
        }
        static inline TString GetInvFilename(const TString& name) {
            return GetIndexPrefix(name) + "inv";
        }
    };
}

class TRTYKIReader: public NRTYServer::TKIProcessorTraits {
private:
    TString FilePath;
    THolder<TYndexRequester> YR;
public:

    typedef TAtomicSharedPtr<TRTYKIReader> TPtr;

    TRTYKIReader(const TString& dir, const TString& name)
        : FilePath(dir + "/" + GetIndexPrefix(name))
    {}

    TYndexRequester* GetYR() {
        VERIFY_WITH_LOG(!!YR, "Incorrect TRTYKIReader usage");
        return YR.Get();
    }

    void Open() {
        NOTICE_LOG << "KeyInv reader for " << FilePath << " opening - " << (ui64)this << Endl;
        VERIFY_WITH_LOG(!YR, "Incorrect TRTYKIReader usage");
        YR.Reset(new TTextRequester(FilePath.data()));
        NOTICE_LOG << "KeyInv reader for " << FilePath << " opened - " << (ui64)this << Endl;
    }

    bool IsOpen() const {
        return  !!YR && YR->IsOpen();
    }

    void Close() {
        NOTICE_LOG << "KeyInv reader for " << FilePath << " closing - " << (ui64)this << Endl;
        VERIFY_WITH_LOG(!!YR, "Incorrect TRTYKIReader usage");
        YR.Destroy();
        // TTextRequester uses global mapping, so we have to release it here
        NRTYServer::ReleaseFileMapping(FilePath + "key");
        NRTYServer::ReleaseFileMapping(FilePath + "inv");
        NOTICE_LOG << "KeyInv reader for " << FilePath << " closed - " << (ui64)this << Endl;
    }

    const TString& GetFilePath() const {
        return FilePath;
    }
};

class TRTYKIMaker: public NRTYServer::TKIProcessorTraits {
private:
    TVector<TAutoPtr<TRTYKIActor> > KIActors;
    TString Dir;
    TString Prefix;

    TAdvancedMergeTaskWriter MergeTaskWriter;

    ui32 ActorsCount;
    ui32 MaxPortionDocs;
public:

    typedef TAtomicSharedPtr<TRTYKIMaker> TPtr;

    TRTYKIMaker(ui32 actorsCount, const TString& dir, const TString& prefix, ui32 maxPortionDocs)
        : Dir(dir)
        , Prefix(prefix)
        , ActorsCount(actorsCount)
        , MaxPortionDocs(maxPortionDocs)
    {
    }

    void Start();

    bool Add(ui32 actorId, IKIStorage& doc, ui32 docId) {
        VERIFY_WITH_LOG(KIActors.size() > actorId, "Incorrect TRTYKIMaker usage");
        return KIActors[actorId]->StoreDoc(doc, docId);
    }

    bool StorePositions(ui32 actorId, const char* key, SUPERLONG* positions, ui32 posCount) {
        VERIFY_WITH_LOG(KIActors.size() > actorId, "Incorrect TRTYKIMaker usage");
        return KIActors[actorId]->StorePositions(key, positions, posCount);
    }

    bool IncDoc(ui32 actorId);

    void Close(const TVector<ui32>* remapTable);

    void Discard();

    void Stop();

};
