#include "builder.h"

#include "parsed_entity.h"
#include "const.h"

#include <saas/rtyserver/components/generator/builder.h>
#include <saas/rtyserver/config/const.h>
#include <robot/jupiter/library/rtdoc/file/model/docidmap.h>

namespace NRTYServer {
    namespace {
        // FIXME(eeight) extract common index frq code
        void WriteIndexFrq(const TString& path, TArrayRef<const ui32> docIds, const THashSet<ui32>& deletedDocids) {
            TFileOutput out(path + "/indexfrq");
            out.SetFinishPropagateMode(true);
            const ui16 presentDoc = 1;
            const ui16 removedDoc = -1;

            for (ui32 docId : docIds) {
                out.Write(
                        docId == NRtDoc::TDocIdMap::DeletedDocument() || deletedDocids.contains(docId) ?
                            &removedDoc : &presentDoc,
                        sizeof(ui16)
                );
            }
            out.Finish();
        }
    }

    TDjBuilder::TDjBuilder(
            const TString& indexFilesPrefix,
            const NDJ::NShard::TSearchIndexBuilder* searchIndexBuilder,
            const bool keepPrepFiles)
        : IIndexComponentBuilder(DjComponentName)
        , Builder(indexFilesPrefix)
        , Manager(new TDjComponentManager())
        , SearchIndexBuilder(searchIndexBuilder)
        , KeepPrepFiles(keepPrepFiles)
    {
    }

    void TDjBuilder::Index(int /*threadId*/, const TParsedDocument& document, const ui32 docId) {
        const TDjParsedEntity* entity = document.GetComponentEntity<TDjParsedEntity>(ComponentName);
        Y_ENSURE(entity);

        const NJupiter::TMercuryLumps* data = entity->GetData();
        Y_ENSURE(data);

        Builder.AddDoc(*data, docId);
    }

    bool TDjBuilder::DoClose(const TBuilderCloseContext& context) {
        Y_ENSURE(context.RemapTable);

        Builder.Finish(context.RemapTable);

        WriteIndexFrq(context.DstDir.PathName(), *context.RemapTable, Manager->GetDeletedDocids());

        TFile jupiIndex(TFsPath(context.DstDir.PathName()) / "jupi_prep_index", WrOnly | OpenAlways);

        if (SearchIndexBuilder) {
            // We don't always build index right here, but when we do, we remove prep files.
            SearchIndexBuilder->Build(context.SrcDir.PathName(), context.DstDir.PathName());
            if (!KeepPrepFiles) {
                Builder.RemovePrepFiles();
            }
        }
        return true;
    }
}
