#include "builder.h"
#include "index.h"

#include <saas/rtyserver/config/common_indexers_config.h>

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

#include <ysite/yandex/common/ylens.h>

ui32 TBaseGeneratorBuilder::GetTrivialResortMap(const IIndexController::TPtr index, TVector<ui32>& result) const {
    ui32 docIdCurrent = 0;
    TSet<ui32> removed(FailedDocs.begin(), FailedDocs.end());
    for (int docId = 0; docId < DocsCount; docId++) {
        if (RTYConfig.GetCommonIndexers().SaveDeletedDocuments || (!index || !index->IsRemoved(docId)) && !removed.contains(docId)) {
            result.push_back(docIdCurrent);
            docIdCurrent++;
        } else {
            result.push_back(-1);
        }
    }
    return docIdCurrent;
}

bool TBaseIndexBuilder::CheckIndexDocIds(const TString& indexPath) const {
    if (!NFs::Exists(indexPath)) {
        return false;
    }

    if (NRTYServer::HasJupiPrep(indexPath)) {
        return true; //do not check lens for preparates
    }

    if (NRTYServer::HasTextWad(indexPath) && !NRTYServer::HasYndex(indexPath)) {
        return true; //Do not check lens if there is no global keyinv
    }

    auto yndex = NRTYServer::GetYndex(indexPath);
    if (!yndex) {
        return false;
    }

    return CheckLens(*yndex);
}

TBaseIndexBuilder::TBaseIndexBuilder(const TRTYServerConfig& rtyConfig, const TString& componentName)
    : TBaseGeneratorBuilder(rtyConfig, componentName)
    , PruningCalcer(TIndexComponentsStorage::Instance().CreatePruningCalcer(nullptr))
{
}

ui32 TBaseIndexBuilder::GetResortMapForMerge(const IIndexController::TPtr index, TVector<ui32>& result) const {
    result.clear();
    if (RTYConfig.Pruning->NeedSort()) {
        TGuardIncompatibleAction gia(ResortMapLocker);
        TSet<ui32> removed(FailedDocs.begin(), FailedDocs.end());
        ui32 docIdCurrent = 0;
        TMap<ui32, ui32> preResult;
        for (TResortMap::const_reverse_iterator i = ResortMap.rbegin(), e = ResortMap.rend(); i != e; ++i) {
            for (TVector<ui32>::const_iterator iv = i->second.begin(); iv != i->second.end(); ++iv) {
                VERIFY_WITH_LOG(preResult.find(*iv) == preResult.end(), "Incorrect builder for map resort on merge portions");
                if (RTYConfig.GetCommonIndexers().SaveDeletedDocuments || (!index || !index->IsRemoved(*iv)) && !removed.contains(*iv)) {
                    preResult[*iv] = docIdCurrent;
                    docIdCurrent++;
                } else {
                    preResult[*iv] = -1;
                }
            }
        }
        for (TMap<ui32, ui32>::const_iterator i = preResult.begin(), e = preResult.end(); i != e; ++i) {
            CHECK_WITH_LOG(i->first == result.size());
            result.push_back(i->second);
        }
        return docIdCurrent;
    } else {
        return GetTrivialResortMap(index, result);
    }
}

void TBaseIndexBuilder::Index(int threadID, const TParsedDocument& document, const ui32 docId) {
    TBaseGeneratorBuilder::Index(threadID, document, docId);
    if (RTYConfig.Pruning->NeedSort()) {
        TGuardTransaction gia(ResortMapLocker);
        ResortMap[PruningCalcer->PruningRankByDoc(&document)].push_back(docId);
    }
}
