#include "disk_manager.h"
#include "const.h"

class TTrigramIndexManagerDisk::TDiskIterator: public TTrigramIndexManager::TIterator {
public:
    TDiskIterator(const IKeysAndPositions& kp, const YxRecord* rec, const IDocProcessor* filter)
        : Filter(filter)
    {
        PosIterator.Init(kp, rec->Offset, rec->Length, rec->Counter, RH_DEFAULT);
        FindFiltered();
    }

    bool Valid() const override {
        return PosIterator.Valid();
    }

    void Next() override {
        ++PosIterator;
        FindFiltered();
    }

    SUPERLONG GetPosition() const override {
        return PosIterator.Current();
    }

private:
    inline void FindFiltered() {
        while (Filter && PosIterator.Valid() && Filter->DocumentBanned(PosIterator.Doc())) {
            ++PosIterator;
        }
    }
    const IDocProcessor* Filter;
    TPosIterator<> PosIterator;
};

bool TTrigramIndexManagerDisk::DoOpen() {
    try {
        Reader.Reset(new TRTYKIReader(Path, "trigram"));
        Reader->Open();
    } catch (...) {
        NOTICE_LOG << "Can't open special trigram data for " << Path << " : " << CurrentExceptionMessage() << Endl;
        return false;
    }
    return Reader && Reader->IsOpen();
}

bool TTrigramIndexManagerDisk::DoClose() {
    CHECK_WITH_LOG(!!Reader);
    if (Reader->IsOpen()) {
        Reader->Close();
    }
    Reader.Destroy();
    return true;
}

bool TTrigramIndexManagerDisk::GetData(const TString& keyName, const TString& value, const IDocProcessor* filter, TSet<SUPERLONG>& result) const {
    TTrigramIndexManager::TIterator::TPtr it = CreateIterator(keyName, value, filter);
    for (; it && it->Valid(); it->Next()) {
        result.insert(it->GetPosition());
    }
    return !!it;
}

TTrigramIndexManager::TIterator::TPtr TTrigramIndexManagerDisk::CreateIterator(const TString& keyName, const TString& value, const IDocProcessor* filter) const {
    if (!Reader)
        return nullptr;
    const TString key(TString::Join(keyName, '@', value));
    TRequestContext rc;
    const YxRecord* rec = ExactSearch(&Reader->GetYR()->YMain(), rc, key.data());
    if (!rec)
        return nullptr;
    return MakeIntrusive<TDiskIterator>(Reader->GetYR()->YMain(), rec, filter);
}
