#include "common.h"

#include <maps/wikimap/mapspro/services/mrc/libs/fb/include/read.h>
#include <maps/wikimap/mapspro/services/mrc/libs/fb/include/version.h>
#include <maps/wikimap/mapspro/services/mrc/libs/fb/include/write.h>

#include <boost/range/algorithm/equal.hpp>

namespace maps::mrc::fb::tests {
namespace {

const auto GRAPH_SCHEMA_VERSION = TSchemaVersion(42);

struct EqualTo {
    bool operator()(const PolylinePosition& lhs,
                    const PolylinePosition& rhs) const
    {
        return lhs.segmentIdx() == rhs.segmentIdx() &&
               lhs.segmentRelPosition() == rhs.segmentRelPosition();
    }

    bool operator()(const CoveredSubPolyline& lhs,
                    const CoveredSubPolyline& rhs) const
    {
        return lhs.featureId() == rhs.featureId() &&
               EqualTo{}(lhs.begin(), rhs.begin()) &&
               EqualTo{}(lhs.end(), rhs.end());
    }

    bool operator()(const TEdgeCoverage& lhs, const TEdgeCoverage& rhs) const
    {
        return lhs.coverageFraction == rhs.coverageFraction &&
               lhs.actualizationDate == rhs.actualizationDate &&
               boost::equal(lhs.coveredSubpolylines,
                            rhs.coveredSubpolylines,
                            EqualTo{}) &&
               lhs.cameraDeviation == rhs.cameraDeviation &&
               lhs.privacy == rhs.privacy;
    }

    bool operator()(const TEdge& lhs, const TEdge& rhs) const
    {
        return lhs.id == rhs.id &&
               boost::equal(lhs.coverages, rhs.coverages, EqualTo{});
    }
};

}  // anonymous namespace

    TEST(test, graph)
    {
        auto testFile = TEST_PATH + "/graph.fb";
        auto bbox = geolib3::BoundingBox{{37.668694, 55.727076},
                                         {37.671280, 55.729366}};
        TEdgeCoverage edgeCoverage{
            .coverageFraction = 0.5f,
            .actualizationDate =
                chrono::parseSqlDateTime("2020-03-30 12:00:00+03"),
            .coveredSubpolylines = {{
                1,
                {0, 0.1},
                {0, 0.2},
            }},
            .cameraDeviation = db::CameraDeviation::Front,
            .privacy = db::FeaturePrivacy::Public};
        auto graph = TGraph{.version = "version",
                            .mrcVersion = "mrcVersion",
                            .schemaVersion = GRAPH_SCHEMA_VERSION};
        for (auto edgeId : rtree().edgesInWindow(bbox)) {
            graph.edges.push_back(
                TEdge{.id = edgeId.value(), .coverages = {edgeCoverage}});
        }
        EXPECT_GT(graph.edges.size(), 0u);
        writeToFile(graph, testFile);
        GraphReader reader{testFile};
        EXPECT_EQ(graph.edges.size(), reader.edgesNumber());
        for (size_t i = 0; i < graph.edges.size(); ++i) {
            EXPECT_TRUE(
                EqualTo{}(graph.edges[i], *reader.edgeById(graph.edges[i].id)));
        }
        EXPECT_EQ(graph.version, reader.version());
        EXPECT_EQ(graph.mrcVersion, reader.mrcVersion());
        EXPECT_EQ(graph.schemaVersion, reader.schemaVersion());
    }

TEST(test, version)
{
    auto time = chrono::parseSqlDateTime("2021-08-18 17:31:59");
    EXPECT_EQ(parseVersion(makeVersion(time)), time);
}

}  // namespace maps::mrc::fb::tests
