#include "manager.h"
#include "parsed_entity.h"

#include <saas/rtyserver/config/const.h>
#include <saas/rtyserver/config/config.h>
#include <saas/rtyserver/config/common_indexers_config.h>
#include <saas/rtyserver/common/common_rty.h>
#include <saas/library/mapping/mapping.h>

#include <robot/library/oxygen/indexer/processor/protos/config.pb.h>

#include <util/string/join.h>

TOXYIndexManager::TOXYIndexManager(const NRTYServer::TManagerConstructionContext& context, TVector<IOxyUpdater::TPtr> updaters, const TString& componentName)
    : TBaseIndexManager(context, componentName)
    , OxygenOptions(Config.GetCommonIndexers().OxygenOptions.Get())
{
    CheckFrqBordersForRemoveFlag = false;
    CHECK_WITH_LOG(!Config.IsPrefixedIndex);
    Updaters = updaters;
}

ui32 TOXYIndexManager::GetDeletedDocumentsCount() const {
    CHECK_WITH_LOG(FA);
    return FA->GetDeletedDocumentsCount();
}

void TOXYIndexManager::InitInteractions(const NRTYServer::IIndexManagersStorage& storage) {
    FA = storage.GetManager<TBaseGeneratorManager>(FULL_ARCHIVE_COMPONENT_NAME);
    CHECK_WITH_LOG(FA);
}

bool TOXYIndexManager::IsRemoved(ui32 docid) const {
    CHECK_WITH_LOG(FA);
    return FA->IsRemoved(docid);
}

ui32 TOXYIndexManager::GetDocumentsCountImpl() const {
    CHECK_WITH_LOG(FA);
    CHECK_WITH_LOG(FA->IsOpened());
    return FA->GetDocumentsCount();
}

ui32 TOXYIndexManager::DoRemoveDocids(const TVector<ui32>& docids) {
    return TBaseIndexManager::DoRemoveDocids(docids);
}

bool TOXYIndexManager::UpdateDoc(ui32 docId, const TParsedDocument::TPtr doc) {
    CHECK_WITH_LOG(!doc->IsNeedRestore());
    const TOXYParsedEntity* docIndex = doc->GetComponentEntity<TOXYParsedEntity>(ComponentName);
    VERIFY_WITH_LOG(docIndex, "there is no Index in doc %s", doc->GetDocSearchInfo().GetUrl().data());
    VERIFY_WITH_LOG(!!docIndex->GetIndexedDoc(), "Incorrect service usage");
    NOxygen::TObjectContext objectContext(docIndex->GetIndexedDoc()->GetKiwiObject());

    for (auto&& i : Updaters) {
        auto result = i->GetTuplesInfo().VerifyObject(objectContext);
        if (result.Correct && !i->Update(docId, objectContext)) {
            throw yexception() << "Incomplete KiwiObject for fast update: " << JoinSeq(" ", result.MissingTupleGroups);
        }
    }

    return true;
}

bool TOXYIndexManager::DoOpen() {
    CHECK_WITH_LOG(OxygenOptions);
    if (TBaseIndexManager::DoOpen()) {
        if (HasPruning() && !FileIndexPrn) {
            const TString& prn = IndexDir.PathName() + "/indexsln";
            if (NFs::Exists(prn)) {
                FileIndexPrn.Reset(NRTYServer::GetFileMapping(UseGlobalMapping, prn, IsReadOnly));
                PrnArray.Reset(new TFileMappedArray<float>());
                PrnArray->Init(*FileIndexPrn);
            }
        }
        return true;
    }
    return false;
}

bool TOXYIndexManager::DoClose() {
    Updaters.clear();
    PrnArray.Reset(nullptr);
    FileIndexPrn.Reset(nullptr);
    return TBaseIndexManager::DoClose();
}

i64 TOXYIndexManager::PrnValue(ui32 docid, i64 defaultValue) const {
    if (HasPruning()) {
        CHECK_WITH_LOG(!!PrnArray);
        if (docid < GetDocumentsCountFrq()) {
            CHECK_WITH_LOG(PrnArray->size() > docid);
            return (i64)1000000 * (*PrnArray)[docid];
        }
    }
    return defaultValue;
}

bool TOXYIndexManager::HasPruning() const {
    if (OxygenOptions) {
        return OxygenOptions->GetSorter().HasPruning() || OxygenOptions->GetRTYProcessorOptions().HasMixerOptions();
    } else {
        return false;
    }
}
