#include "search_archive_normalizer.h"

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

#include <kernel/multipart_archive/convert/flat2multipart.h>
#include <kernel/multipart_archive/multipart.h>
#include <kernel/tarc/iface/tarcio.h>

TSearchArchiveNormalizer::TSearchArchiveNormalizer(const TRTYServerConfig& config)
    : NRTYServer::INormalizer(config)
{}

const char* TSearchArchiveNormalizer::Name() const {
    return "SearchArchive";
}

bool TSearchArchiveNormalizer::AllRight(const NRTYServer::TNormalizerContext& context, const THolder<TFileMap>& indexFrq) const {
    TFsPath dir(context.Dir.PathName() + "/indexdir");
    CHECK_WITH_LOG(!!indexFrq.Get());

    INFO_LOG << "check search archive before normalization for " << context.Dir.PathName() << Endl;

    switch(context.Config.GetSearcherConfig().ArchiveType) {
        case AT_MULTIPART:
            return TArchiveOwner::Exists(context.Dir.PathName() + "/indexarc");
        case AT_FLAT:
            return dir.Exists() && (ui64(TFile(dir, RdOnly).GetLength()) == ui64(indexFrq->Length() / sizeof(i16) * sizeof(ui64)));
        default:
            FAIL_LOG("Unknown archive type");
    }

    return false;
}

void TSearchArchiveNormalizer::Fix(const NRTYServer::TNormalizerContext& context, const THolder<TFileMap>& indexFrq) const {
    const TFsPath indexdir(context.Dir.PathName() + "/indexdir");
    const TFsPath indexarc(context.Dir.PathName() + "/indexarc");
    CHECK_WITH_LOG(!!indexFrq.Get());
    ui32 docsCount = ui64(indexFrq->Length() / sizeof(i16));

    INFO_LOG << "start search archive normalization for " << context.Dir.PathName() << Endl;

    NRTYServer::IIndexOwner::TGuardIndexModification g(context.Index);
    switch(context.Config.GetSearcherConfig().ArchiveType) {
        case AT_MULTIPART:
        {
            AssertCorrectIndex(indexdir.Exists(), "Can't find %s in TSearchArchiveNormalizer", indexdir.GetPath().data());
            AssertCorrectIndex(indexarc.Exists(), "Can't find %s in TSearchArchiveNormalizer", indexarc.GetPath().data());
            const TString& multipartPrefix = indexarc;
            NRTYArchive::ConvertFlatArchiveToMultipart(indexdir,
                                                       indexarc,
                                                       multipartPrefix,
                                                       context.Config.GetCommonIndexers().TextArchiveParams);
            indexdir.ForceDelete();
            indexarc.ForceDelete();
            break;
        }
        case AT_FLAT:
        {
            if (!indexarc.Exists()) {
                if (TArchiveOwner::Exists(indexarc)) {
                    if (!TArchiveOwner::Check(indexarc)) {
                        TArchiveOwner::Repair(indexarc, context.Config.GetCommonIndexers().TextArchiveParams);
                    }
                    NRTYArchive::ConvertMultipartArchiveToFlat(indexarc, context.Config.GetCommonIndexers().TextArchiveParams, context.Dir.PathName() + "/index");
                    TArchiveOwner::Remove(indexarc);
                } else {
                    AssertCorrectIndex(docsCount == 0, "Can't restore not empty flat archive without indexarc file");
                }
            }
            MakeArchiveDir(indexarc, indexdir);
            break;
        }
        default:
            FAIL_LOG("Unknown archive type");
    }

    INFO_LOG << "search archive normalization for " << context.Dir.PathName() << " finished." << Endl;
}
