#pragma once
#include <library/cpp/logger/global/global.h>
#include <library/cpp/wordpos/wordpos.h>

class TQSPosBuilder {
public:
    static bool BuildHits(SUPERLONG& hitLow, SUPERLONG& hitHigh, ui32 docId, ui32 position) {
        hitLow = hitHigh = 0;
        ui32 w0 = position & ((1 << 6) - 1);
        ui32 b0 = (position >> 6) & ((1 << 15) - 1);
        ui32 b1 = position >> (6 + 15);
        TWordPosition::SetDoc(hitLow, docId);
        TWordPosition::SetBreak(hitLow, b0);
        TWordPosition::SetWord(hitLow, w0);

        TWordPosition::SetDoc(hitHigh, docId);
        TWordPosition::SetBreak(hitHigh, b1);
        TWordPosition::SetRelevLevel(hitHigh, 1);
        return true;
    }

    static bool BuildHits(TWordPosition& hitLow, TWordPosition& hitHigh, ui32 docId, ui32 pos) {
        SUPERLONG h1 = hitLow.SuperLong();
        SUPERLONG h2 = hitLow.SuperLong();
        BuildHits(h1, h2, docId, pos);
        hitLow = h1;
        hitHigh = h2;
        return true;
    }

    static bool BuildPosition(const TWordPosition& hit0, const TWordPosition& hit1, ui32& pos) {
        ui32 b0 = hit0.Break();
        ui32 w0 = hit0.Word();
        ui32 r0 = hit0.GetRelevLevel();

        ui32 b1 = hit1.Break();
        ui32 w1 = hit1.Word();
        ui32 r1 = hit1.GetRelevLevel();

        if (r1 && r0) {
            ERROR_LOG << "Incorrect positions r0 && r1 check failed: " << hit0.SuperLong() << "-" << hit1.SuperLong() << Endl;
            Y_ASSERT(0);
            return false;
        }

        if (r1) {
            pos = w0 + (b0 << 6) + (b1 << (6 + 15));
        } else if (r0) {
            pos = w1 + (b1 << 6) + (b0 << (6 + 15));
        } else {
            ERROR_LOG << "Incorrect positions r0 ^ r1 check failed: " << hit0.SuperLong() << "-" << hit1.SuperLong() << Endl;
            Y_ASSERT(0);
            return false;
        }

        return true;
    }
};
