#include "indexer_core.h"

#include <saas/rtyserver/config/common_indexers_config.h>
#include <saas/rtyserver/config/config.h>
#include <saas/rtyserver/config/grouping_config.h>
#include <saas/rtyserver/config/indexer_config.h>
#include <saas/rtyserver/config/realm_config.h>

#include <saas/util/logging/exception_process.h>

NRTYServer::TBuilderConstructionContext TIndexerCore::GetBuildersContructionContext() {
    return NRTYServer::TBuilderConstructionContext(Config, DirConfig, BaseConfig, TempDir, GetRealm(), GetRealmName());
}

void TIndexerCore::UpdateIndexerTimestamp(const TParsedDocument& document) {
    Timestamp.Update(document.GetStreamId(), document.GetTimestamp());
    for (auto&& extra : document.GetExtraTimestamps()) {
        Timestamp.Update(extra.first, extra.second);
    }
}

void TIndexerCore::UpdateIndexerPositions(const TParsedDocument& document) {
    auto streamId = document.GetStreamId();
    auto position = document.GetPosition();
    if (position) {
        Positions.Update(streamId, position->GetKey(), position->GetValue());
    }
    for (auto&& positionIt : document.GetExtraPositions()) {
        Positions.Update(streamId, positionIt.GetKey(), positionIt.GetValue());
    }
}

TIndexerCore::TIndexerCore(const TString& indexDirName, const TString& tempDirName, const TString& rootDir,
                           const NRTYServer::TIndexerConfig& config, ui32 shard)
    : Config(config)
    , Shard(shard)
    , Capacity(config.MaxDocuments)
    , DocId(0)
    , Timestamp(rootDir + "/" + tempDirName)
    , Positions(rootDir + "/" + tempDirName)
    , Dir(rootDir + "/" + indexDirName)
    , TempDir(rootDir + "/" + tempDirName)
{
    TRY
        VERIFY_WITH_LOG(!rootDir.empty(), "rootDir is empty");
        VERIFY_WITH_LOG(indexDirName == TFsPath(indexDirName).Basename(), "indexDirName is a path");
        VERIFY_WITH_LOG(tempDirName == TFsPath(tempDirName).Basename(), "tempDirName is a path");
        VERIFY_WITH_LOG(indexDirName != tempDirName, "indexDirName and tempDirName are equal");

        TString workDir(rootDir);
        SlashFolderLocal(workDir);

        DirConfig.TempDir = TempDir.PathName();
        SlashFolderLocal(DirConfig.TempDir);
        if (!IsDir(DirConfig.TempDir)) {
            if (mkpath(DirConfig.TempDir.begin()) || !IsDir(DirConfig.TempDir))
                ythrow yexception() << "directory '" << DirConfig.TempDir << "' does not exist and cannot be created: " << LastSystemErrorText();
        }

        DirConfig.OldPrefix = Dir.PathName() + "/";
        if (!IsDir(DirConfig.OldPrefix)) {
            if (mkpath(DirConfig.OldPrefix.begin()) || !IsDir(DirConfig.OldPrefix))
                ythrow yexception() << "directory '" << DirConfig.OldPrefix << "' does not exist and cannot be created: " << LastSystemErrorText();
        }
        DirConfig.OldPrefix += "index";
        DirConfig.TempPrefix = DirConfig.TempDir + "tmp";
        DirConfig.NewPrefix = DirConfig.TempDir + "index";
        BaseConfig.DocCount = config.Common.Owner.GetRealmListConfig().GetMainRealmConfig().GetIndexerConfigDisk().PortionDocCount;
        BaseConfig.RecognizeLibraryFile = Config.Common.RecognizeLibraryFile;
        BaseConfig.Groups = Config.Common.GroupingConfig->ToString();
        BaseConfig.DocProperties = Config.Common.DocProperty;
        BaseConfig.UseExtProcs = Config.Common.Owner.UseExtendedProcessors;
        BaseConfig.NoMorphology = Config.Common.Owner.NoMorphology;
        BaseConfig.NeededFreqKeys.clear();
        if(!Config.Common.NoNeededFreqKeys)
            BaseConfig.NeededFreqKeys.insert(FDI_DOC_LEN);
        BaseConfig.UseArchive = Config.Common.Owner.DoStoreArchive;
        BaseConfig.ParserConfig = Config.Common.HtmlParserConfigFile;
        BaseConfig.XmlParserConf = Config.Common.XmlParserConfigFile;
        BaseConfig.UseHTML5Parser = Config.Common.UseHTML5Parser;
        BaseConfig.UseOldC2N = false;
        BaseConfig.WorkDir = workDir;
        BaseConfig.OldAttrPath = DirConfig.OldPrefix;
        BaseConfig.NewAttrPath = DirConfig.NewPrefix;
        BaseConfig.CheckConfigsExists();
        BaseConfig.ResolveWorkDir();

    CATCH_AND_RETHROW("while initializing index " + Directory().PathName())
}

const TString& TIndexerCore::IndexerType() const {
    return Config.GetType();
}
