#include "sequential_write_makeup_manager.h"

#include <library/cpp/logger/global/global.h>

TSequentialWriteMakeupStorage::TSequentialWriteMakeupStorage(const TRTYServerConfig& config)
    : ZonesDescription(config)
{
}

void TSequentialWriteMakeupStorage::StoreZone(ui32 docId, NZonesMakeup::TZoneNumber numZone,
    ui16 sentBegin, ui16 wordBegin, ui32 wordBeginInDoc, ui16 sentEnd, ui16 wordEnd, ui32 wordEndInDoc)
{
    VERIFY_WITH_LOG(docId == CurrentDocId, "DocIds mismatch");
    CurrentDocument->StoreZone(numZone, sentBegin, wordBegin, wordBeginInDoc, sentEnd, wordEnd, wordEndInDoc);
}

void TSequentialWriteMakeupStorage::MarkDocNoZones(ui32 docId) {
    VERIFY_WITH_LOG(docId == CurrentDocId, "DocIds mismatch");
    CurrentDocument.Reset(new NZonesMakeup::TDocumentMakeup(this, true));
}

void TSequentialWriteMakeupStorage::BuildMakeup(ui32 docId) {
    VERIFY_WITH_LOG(docId == CurrentDocId, "DocIds mismatch");
    CurrentDocument->BuildMakeup();
}

NZonesMakeup::TZoneNumber TSequentialWriteMakeupStorage::DecodeZone(const TString& name) {
    return ZonesDescription.Decode(name).ZoneNumber;
}

void TSequentialWriteMakeupStorage::AddZone(const TString& name) {
    ZonesDescription.AddZone(name);
}

void TSequentialWriteMakeupStorage::AddZoneUnsafe(const TString& name) {
    ZonesDescription.AddZoneUnsafe(name);
}

TOptionalAllocator& TSequentialWriteMakeupStorage::GetTempStorageAllocator() {
    return TempStorageAllocator;
}

bool TSequentialWriteMakeupStorage::GetDoClean() const {
    return false;
}

NZonesMakeup::IZonesDescription* TSequentialWriteMakeupStorage::GetZonesDescription() {
    return &ZonesDescription;
}

const NZonesMakeup::IZonesDescription* TSequentialWriteMakeupStorage::GetZonesDescription() const {
    return &ZonesDescription;
}

TMakeupAllocatorsStorage& TSequentialWriteMakeupStorage::GetAllocatorsStorage() {
    return AllocatorStorage;
}


void TSequentialWriteMakeupStorage::StartDocId(const ui32 docId) {
    CurrentDocId = docId;
    CurrentDocument.Reset(new NZonesMakeup::TDocumentMakeup(this, true));
}

void TSequentialWriteMakeupStorage::FinishDocId(const ui32 docId) {
    VERIFY_WITH_LOG(docId == CurrentDocId, "DocIds mismatch");
    CurrentDocId = Max<ui32>();
    CurrentDocument.Reset();
}

void TSequentialWriteMakeupStorage::SerializeZonesDescription(IOutputStream& output, const ui32 docCount) {
    ZonesDescription.SerializeForMerger(output, docCount);
}

void TSequentialWriteMakeupStorage::SerializeCurrentDocument(IOutputStream& output) {
    CurrentDocument->Serialize(output, false);
}

IMakeupWritableStorage* TSequentialWriteMakeupManager::GetMakeupStorage() {
    return &MakeupStorage;
}

TSequentialWriteMakeupManager::TSequentialWriteMakeupManager(const TRTYServerConfig& config, const ui32 docsCount)
    : MakeupStorage(config)
    , Savers(docsCount, TMakeupSaver(this, config.IsPrefixedIndex))
    , IsPrefixed(config.IsPrefixedIndex)
{
}

void TSequentialWriteMakeupManager::Serialize(IOutputStream& hdrOutput, IOutputStream& docsOutput) {
    MakeupStorage.SerializeZonesDescription(hdrOutput, Savers.size());
    for (ui32 docId = 0; docId < Savers.size(); ++docId) {
        MakeupStorage.StartDocId(docId);
        Savers[docId].Finish(docId);
        MakeupStorage.SerializeCurrentDocument(docsOutput);
        Savers[docId].Reset();
        MakeupStorage.FinishDocId(docId);
    }
    hdrOutput.Finish();
    docsOutput.Finish();
}

void TSequentialWriteMakeupManager::StorePosition(const ui32 docId, const char* key, SUPERLONG position) {
    //FIXME Broken logic since (C) is the word
    if (key[0] == '(' || key[0] == ')' || key[0] == '#') {
        Savers[docId].StorePositionsAttr(key, &position, 1);
    } else {
        Savers[docId].StorePositionsLemm(key, &position, 1);
    }
}

bool TSequentialWriteMakeupManager::IsZoneForStore(const char* key) const {
    return TMakeupSaver::IsKeyInteresting(key) && TMakeupSaver::IsZoneForSaving(key, IsPrefixed);
}
