#include "erf_builder.h"

#include <saas/rtyserver/indexer_core/parsed_document.h>

TRTYErfBuilder::TRTYErfBuilder(IRTYErfManager* manager, const TString& componentName)
    : NRTYServer::IIndexComponentBuilder(componentName)
    , ErfManager(manager)
    , ErfWriter(manager)
    , StaticFactors(manager ? manager->GetFactorsInfo() : nullptr)
{
    if (ErfManager) {
        VERIFY_WITH_LOG(ErfManager->Open(), "Cannot open ERF manager");
        VERIFY_WITH_LOG(StaticFactors, "Static factors description is empty");
    }
}

TRTYErfBuilder::~TRTYErfBuilder() {
    if (ErfManager)
        ErfManager->Close();
}

void TRTYErfBuilder::Index(int /*threadID*/, const TParsedDocument& document, const ui32 docId) {
    if (!ErfManager) {
        return;
    }

    TBasicFactorStorage data(StaticFactors->GetStaticFactorsCount());
    data.Clear();
    CHECK_WITH_LOG(StaticFactors->LoadErfBlock(data, document));
    VERIFY_WITH_LOG(ErfWriter.Write(data, docId), "Incorrect usage erf.write (%u >= %u)", docId, ErfManager->Size());
}

bool TRTYErfBuilder::DoClose(const NRTYServer::TBuilderCloseContext& /*context*/) {
    return ErfManager ? ErfManager->Close() : true;
}

TRTYMemoryErfBuilder::TRTYMemoryErfBuilder(IRTYErfManager* manager, const TString& componentName)
    : TRTYErfBuilder(manager, componentName)
{}

bool TRTYMemoryErfBuilder::DoClose(const NRTYServer::TBuilderCloseContext & context) {
    VERIFY_WITH_LOG(context.SrcDir == context.DstDir, "Not supported");
    return TRTYErfBuilder::DoClose(context);
}

TRTYDiskErfBuilder::TRTYDiskErfBuilder(IRTYErfManager* manager, const TRTYErfDiskManager::TCreationContext& diskManagerCtx, const TString& componentName)
    : TRTYErfBuilder(manager, componentName)
    , DiskManagerCtx(diskManagerCtx)
{}

bool TRTYDiskErfBuilder::DoClose(const NRTYServer::TBuilderCloseContext& context) {
    if (!ErfManager)
        return true;

    const ui32 factorsCount = StaticFactors->GetStaticFactorsCount();

    VERIFY_WITH_LOG(!!context.RemapTable, "Incorrect usage erf builder close method");
    int newSize = 0;
    for (TVector<ui32>::const_iterator i = context.RemapTable->begin(); i != context.RemapTable->end(); ++i) {
        if (*i != REMAP_NOWHERE) {
            ++newSize;
        }
    }
    const TString finalFileName = DiskManagerCtx.FileName;
    NOTICE_LOG << "resize ddk for " << finalFileName << " as " << newSize << Endl;
    DiskManagerCtx.BlockCount = newSize;
    DiskManagerCtx.Directory = context.DstDir;
    DiskManagerCtx.FileName += ".temp";
    TRTYErfDiskManager newErfDisk(DiskManagerCtx, ErfManager->GetComponentName());
    newErfDisk.Open();
    {
        TBasicFactorStorage data(factorsCount);
        for (int docid = 0; docid < context.RemapTable->ysize(); ++docid) {
            VERIFY_WITH_LOG(ErfManager->ReadRaw(data, docid), "incorrect erf close: %d >= %u", docid, ErfManager->Size());
            if ((*context.RemapTable)[docid] != REMAP_NOWHERE) {
                newErfDisk.Write(data, (*context.RemapTable)[docid]);
            }
        }
    }
    newErfDisk.Close();
    newErfDisk.RenameTo(context.DstDir.PathName(), finalFileName);
    return true;
}
