#include <library/cpp/testing/gtest/gtest.h>

#include <maps/wikimap/mapspro/services/mrc/libs/common/include/joined_ranges_iterator.h>

#include <util/generic/iterator_range.h>

#include <vector>

namespace maps::mrc::common::tests {

namespace {

using Container = std::vector<int>;
using Iterator = Container::iterator;

Container join(const std::vector<Container>& inputRanges)
{
    Container result;
    for (const auto& range : inputRanges) {
        for (auto value : range) {
            result.push_back(value);
        }
    }
    return result;
}

std::vector<TIteratorRange<Iterator>>
makeIteratorRanges(std::vector<Container>& inputRanges)
{
    std::vector<TIteratorRange<Iterator>> result;
    result.reserve(inputRanges.size());
    for (auto& range : inputRanges) {
        result.push_back(MakeIteratorRange(std::begin(range), std::end(range)));
    }
    return result;
}

} // namespace

TEST(joined_ranges_iterator_should, basic_test)
{
    using TestDatum = std::vector<Container>;

    std::vector<TestDatum> testData {
        {{}},
        {{1}, {1, 2, 3}, {}, {5}}
    };

    for (auto& testDatum : testData) {
        Container result(JoinedRangesIterator<Iterator>(makeIteratorRanges(testDatum)), JoinedRangesIterator<Iterator>());
        EXPECT_THAT(result, testing::ContainerEq(join(testDatum)));
    }
}

TEST(joined_ranges_iterator_should, equals)
{
    using TestDatum = std::vector<Container>;

    std::vector<TestDatum> testData {
        {{}},
        {{1}, {1, 2, 3}, {}, {5}}
    };

    JoinedRangesIterator<Iterator> it1(makeIteratorRanges(testData[0]));
    JoinedRangesIterator<Iterator> it2(makeIteratorRanges(testData[1]));
    JoinedRangesIterator<Iterator> end;

    EXPECT_EQ(it1, it1);
    EXPECT_EQ(end, end);
    EXPECT_NE(it1, it2);

    auto nextIt2 = std::next(it2);
    EXPECT_NE(it2, nextIt2);
    EXPECT_EQ(nextIt2, std::next(it2));

    ++nextIt2;
    EXPECT_NE(it2, nextIt2);
}


} // namespace maps::mrc::common::tests
