#include "read_write_makeup_manager.h"
#include "sequential_write_makeup_manager.h"
#include "makeup_saver.h"

#include <library/cpp/testing/unittest/registar.h>


Y_UNIT_TEST_SUITE(SequentialWriteManagerSuite) {

    struct TIndexPos {
        TString Key;
        SUPERLONG Pos;
    };

    TVector<TVector<TIndexPos>> docs = {
        {
            {"(0000000000012705?item_0", 28736},
            {")0000000000012705?item_0", 41072},
            {"(0000000000012705?item_1", 16448},
            {")0000000000012705?item_1", 28784}
        },
        {
            {"(0000000000012705?item_0", 114353545280},
            {")0000000000012705?item_0", 114353557616},
            {"(0000000000012705?item_1", 114353532992},
            {")0000000000012705?item_1", 114353545328},
            {"(0000000000012705?item_2", 114353520704},
            {")0000000000012705?item_2", 114353533040}
        },
        {
            {"(0000000000012700?item_3", 416670212464704},
            {")0000000000012700?item_3", 416670212477040},
            {"(0000000000012700?item_4", 416670212440128},
            {")0000000000012700?item_4", 416670212452464},
            {"(0000000000012700?item_5", 416670212501568},
            {")0000000000012700?item_5", 416670212513904}
        }
    };

    template<typename TIter>
    THolder<TReadWriteRTYMakeupManager> BuildIndexRW(const TIter& begin, const TIter& end) {
        TRTYServerConfig config(MakeAtomicShared<TDaemonConfig>(TDaemonConfig::DefaultEmptyConfig.data(), false));
        config.IsPrefixedIndex = true;
        const ui32 docsCount = std::distance(begin, end);
        THolder<TReadWriteRTYMakeupManager> readWriteManager = MakeHolder<TReadWriteRTYMakeupManager>(docsCount, config, false, false, false);
        ui32 docId = 0;
        for (auto it = begin; it != end; ++it) {
            TMakeupSaver saver(readWriteManager.Get(), true);
            for (auto propIt = it->begin(); propIt != it->end(); ++propIt) {
                const SUPERLONG pos = propIt->Pos;
                saver.StorePositionsAttr(propIt->Key.c_str(), &pos, 1);
            }
            saver.Finish(docId++);
        }
        return readWriteManager;
    }

    template<typename TIter>
    std::pair<TString, TString> BuildIndexSequential(const TIter& begin, const TIter& end) {
        TRTYServerConfig config(MakeAtomicShared<TDaemonConfig>(TDaemonConfig::DefaultEmptyConfig.data(), false));
        config.IsPrefixedIndex = true;
        const ui32 docsCount = std::distance(begin, end);

        TSequentialWriteMakeupManager sequentialWriteManager(config, docsCount);

        ui32 docId = 0;
        for (auto it = begin; it != end; ++it) {
            for (auto propIt = it->begin(); propIt != it->end(); ++propIt) {
                sequentialWriteManager.StorePosition(docId, propIt->Key.c_str(), propIt->Pos);
            }
            ++docId;
        }

        TString hdrRes;
        TString docsRes;
        TStringOutput hdrOut(hdrRes);
        TStringOutput docsOut(docsRes);
        sequentialWriteManager.Serialize(hdrOut, docsOut);
        return std::make_pair(hdrRes, docsRes);
    }

    THolder<TReadWriteRTYMakeupManager> ParseIdx(const std::pair<TString, TString>& idx) {
        TRTYServerConfig config(MakeAtomicShared<TDaemonConfig>(TDaemonConfig::DefaultEmptyConfig.data(), false));
        config.IsPrefixedIndex = true;
        THolder<TReadWriteRTYMakeupManager> readWriteManager = MakeHolder<TReadWriteRTYMakeupManager>(0, config, false, false, false);
        TStringInput hdrInp(idx.first);
        TStringInput docsInp(idx.second);
        readWriteManager->Deserialize(hdrInp, docsInp);
        return readWriteManager;
    }

    Y_UNIT_TEST(TestSerializationTrivial) {
        THolder<TReadWriteRTYMakeupManager> readWriteManager = BuildIndexRW(docs.begin(), docs.end());
        TString hdrIdx;
        TString docsIdx;
        TStringOutput hdrOut(hdrIdx);
        TStringOutput docsOut(docsIdx);
        readWriteManager->Serialize(hdrOut, docsOut, nullptr);

        THolder<TReadWriteRTYMakeupManager> parsedIdx = ParseIdx(std::make_pair(hdrIdx, docsIdx));
        UNIT_ASSERT_EQUAL(*parsedIdx, *readWriteManager);
    }

    Y_UNIT_TEST(TestSerializationSequential) {
        std::pair<TString, TString> idx = BuildIndexSequential(docs.begin(), docs.end());

        THolder<TReadWriteRTYMakeupManager> parsedIdx = ParseIdx(idx);

        THolder<TReadWriteRTYMakeupManager> readWriteManager = BuildIndexRW(docs.begin(), docs.end());
        UNIT_ASSERT_EQUAL(*parsedIdx, *readWriteManager);
    }

}
