#include "component.h"

#include <saas/rtyserver/config/config.h>
#include <saas/rtyserver/config/merger_config.h>
#include <saas/rtyserver/config/searcher_config.h>

#include <saas/library/mapping/mapping.h>

#include <library/cpp/logger/global/global.h>
#include <library/cpp/streams/special/buffered_throttled_file.h>


namespace {
    const TString IndexFile = "url2docid";

    bool IsUsed(const TRTYServerConfig& config) {
        return config.UrlToDocIdManager == URL2DOCID_COMPONENT_NAME || config.ComponentsSet.contains(URL2DOCID_COMPONENT_NAME);
    }
}


TUrlToDocIdComponent::TUrlToDocIdComponent(const TRTYServerConfig& config)
    : IIndexComponent(IsUsed(config))
    , ComponentConfig(*(config.ComponentsConfig.Get<TUrlToDocIdConfig>(URL2DOCID_COMPONENT_NAME)))
    , Config(config)
    , HashToDocId(ComponentConfig.GetUseGlobalMapping())
{
    IndexFiles.insert(TIndexFile(IndexFile, true, config.GetSearcherConfig().LockUrl2DocId ? TIndexFile::EPrefetchPolicy::ppLock : TIndexFile::EPrefetchPolicy::ppDisable));
}

THolder<NRTYServer::IIndexComponentBuilder> TUrlToDocIdComponent::CreateBuilder(const NRTYServer::TBuilderConstructionContext&) const {
    return MakeHolder<TUrlToDocIdBuilder>(IndexFile, URL2DOCID_COMPONENT_NAME, ComponentConfig);
}

THolder<NRTYServer::IIndexComponentManager> TUrlToDocIdComponent::CreateManager(const NRTYServer::TManagerConstructionContext& context) const {
    if (context.IndexType != IIndexController::FINAL && context.IndexType != IIndexController::PREPARED) {
        return nullptr;
    }
    return MakeHolder<TUrlToDocIdManager>(TFsPath(context.Dir.PathName() + "/" + IndexFile), URL2DOCID_COMPONENT_NAME, ComponentConfig, Config.GetMergerConfig().WriteOption);
}

NRTYServer::IComponentParser::TPtr TUrlToDocIdComponent::BuildParser() const {
    return nullptr;
}

NRTYServer::IParsedEntity::TPtr TUrlToDocIdComponent::BuildParsedEntity(NRTYServer::IParsedEntity::TConstructParams&) const {
    return nullptr;
}

bool TUrlToDocIdComponent::DoAllRight(const NRTYServer::TNormalizerContext& context) const {
    return CheckPath(context);
}

bool TUrlToDocIdComponent::CheckPath(const NRTYServer::TNormalizerContext& context) const {
    const TString filePath = context.Dir.PathName() + "/" + IndexFile;
    auto indexGenerator = context.Managers.GetIndexManager();
    ui64 docCount = Max<ui64>();
    if (indexGenerator) {
        docCount = indexGenerator->GetSearchableDocumentsCount();
    }
    return HashToDocId.CheckPath(filePath, docCount);

}
void TUrlToDocIdComponent::CheckAndFix(const NRTYServer::TNormalizerContext& context) const {
    if (CheckPath(context)) {
        return;
    }
    bool isReadOnly = Config.IsReadOnly;
    const TString filePath = context.Dir.PathName() + "/" + IndexFile;
    NOTICE_LOG << filePath << " corrupted" << Endl;

    auto indexGenerator = context.Managers.GetIndexManager();
    ui64 docCount = Max<ui64>();
    if (indexGenerator) {
        docCount = indexGenerator->GetSearchableDocumentsCount();
    }
    NOTICE_LOG << "docs count from index generator " << docCount << " ; " << "docs count from storage " << context.Managers.GetDocumentsCount() << Endl;
    AssertCorrectIndex(!isReadOnly, filePath + " doesn't exist and cannot be created in read-only mode");

    HashToDocId.Rebuild(THashStorageAdapter(context.Managers), filePath, Config.GetMergerConfig().WriteOption);
}
