#include "frq_normalizer.h"

#include <saas/rtyserver/components/fullarchive/disk_manager.h>
#include <saas/util/logging/exception_process.h>

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

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

const char* TIndexFrqNormalizer::Name() const {
    return "indexfrq";
}

bool TIndexFrqNormalizer::AllRight(const NRTYServer::TNormalizerContext& context, const THolder<TFileMap>& indexFrq) const {
    if (!indexFrq || context.Index->GetYndex() == nullptr)
        return false;
    const ui32 yndexDocCount = GetYndexDocCount(*context.Index->GetYndex());
    if (indexFrq->MappedSize() != yndexDocCount * sizeof(i16))
        return false;
    const TDiskFAManager* fullArc = context.Managers.GetManager<TDiskFAManager>(FULL_ARCHIVE_COMPONENT_NAME);
    VERIFY_WITH_LOG(fullArc && fullArc->IsOpened(), "Fullarc must be opened");
    const i16* deleted = (const i16*)indexFrq->Ptr();
    for (ui32 docId = 0; docId < yndexDocCount; ++docId) {
        const bool isFARemoved = fullArc->IsRemoved(docId);
        const bool isFRQRemoved = (deleted[docId] == -1);
        if (isFARemoved ^ isFRQRemoved) {
            DEBUG_LOG << "indexFrq has deleted status mismatch at docid: " << docId << "; FA: " << isFARemoved << "; Frq: " << isFRQRemoved << Endl;
            return false;
        }
    }
    return true;
}

void TIndexFrqNormalizer::Fix(const NRTYServer::TNormalizerContext& context, const THolder<TFileMap>& /*indexFrq*/) const {
    TRY
        Y_ENSURE(context.Index->GetYndex() != nullptr);
        const TString frq = context.Dir.PathName() + "/indexfrq";
        const ui32 docNum = GetYndexDocCount(*context.Index->GetYndex());
        TVector<i16> data(docNum, 0);
        const TDiskFAManager* fullArc = context.Managers.GetManager<TDiskFAManager>(FULL_ARCHIVE_COMPONENT_NAME);
        VERIFY_WITH_LOG(fullArc && fullArc->IsOpened(), "Fullarc must be opened");
        for (ui32 docId = 0; docId < docNum; ++docId) {
            if (fullArc->IsRemoved(docId)) {
                data[docId] = -1;
            }
        }
        NRTYServer::IIndexOwner::TGuardIndexModification g(context.Index);
        TFileHandle frqFile(frq.data(), OpenAlways);
        frqFile.Resize(docNum * sizeof(i16));
        frqFile.Write(&data[0], data.size() * sizeof(data[0]));
        frqFile.Close();
        return;
    CATCH("On RepairIndexFrq");
    VERIFY_WITH_LOG(false, "Incorrect normalization: RepairIndexFrq")
}
