#include "mingeo_normalizer.h"
#include "mingeo_index.h"
#include "mingeo_core.h"
#include "mingeo_builder.h"
#include "geo_kdtree.h"

using namespace NRTYGeo;

namespace NRTYServer {
    bool TMinGeoInvNormalizer::AllRight(const NRTYServer::TNormalizerContext& context, const THolder<TFileMap>& indexFrq) const {
        if (!TL2Normalizer::AllRight(context, indexFrq))
            return false;
        TFsPath invFile = TGeoIndexFormatter::FormatFileName(TFsPath(context.Dir.PathName()), "index");
        if (!invFile.Exists() || !TGeoIndexFormatter::Check(invFile))
            return false;

        return true;
    }

    void TMinGeoInvNormalizer::LoadKpsByDocId(TVector<ui64>& kpsTable, const NRTYServer::TNormalizerContext& context) const {
        const ui32 maxDocId = TL2Normalizer::GetMaxDocId(context);
        if (maxDocId != Max<ui32>())
            kpsTable.resize(maxDocId + 1, 0ull);

        THolder<IDocSearchInfoIterator> iter = TL2Normalizer::CreateDocSearchInfoIterator(context);
        CHECK_WITH_LOG(iter);
        for (; iter->IsValid(); iter->Next()) {
            TDocSearchInfo item = iter->Get();
            ui32 docId = item.GetDocId();
            Y_ASSERT(docId < kpsTable.size());
            if (docId >= kpsTable.size()) {
                kpsTable.resize(docId + 1);
            }
            kpsTable[docId] = item.GetKeyPrefix();
        }
    }

    void TMinGeoInvNormalizer::Fix(const NRTYServer::TNormalizerContext& context, const THolder<TFileMap>& indexFrq) const {
        Y_UNUSED(indexFrq);
        
        TFsPath invFile = TGeoIndexFormatter::FormatFileName(TFsPath(context.Dir.PathName()), "index");

        if (invFile.Exists() && !TGeoIndexFormatter::Check(invFile)) {
            WARNING_LOG << "Removing the debris of old " << invFile.Basename() << " in " << context.Dir.PathName() << Endl;
            invFile.DeleteIfExists(); //throws on failure
        }

        if (!invFile.Exists()) {
            // rebuild index from the archive
            TVector<ui64> keyPrefixes;
            LoadKpsByDocId(keyPrefixes, context); // get KeyPrefix from either Base layer or Full layer

            NRTYGeo::TGeoIndexBuilder bld;
            TL2IteratorBase::TPtr iter = CreateInputIterator(context);
            for (; iter->IsValid(); iter->Next()) {
                TBlob item = iter->GetCurrent();

                //(SAAS-5718) this logic should use TL2DocEntity instead of TRecord
                TMinGeoParser::TRecord record;
                if (!TMinGeoParser::TryLoad(item, record))
                    continue;

                const ui32 docId = iter->GetDocId();
                TGeoTransientEntity::TBuilderInvData builderInv = TMinGeoParser::MakeBuilderInvData(record, keyPrefixes[docId]);
                TMinGeoBuilder::Index(bld, builderInv, iter->GetDocId());
            }
            NRTYGeo::TGeoIndex index;
            bld.Finalize(index);
            NRTYGeo::TGeoIndexFormatter::Save(invFile, index);
        }
    }
}
