#include <library/cpp/testing/gtest/gtest.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/feedback/include/object.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/location/include/rotation.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/unit_test/include/frame.h>

using namespace maps::mrc::db::eye;

namespace maps::mrc::eye::tests {

TEST(set_object_attrs_tests, set_sign_attrs_test)
{
    HypothesisContext context({
        {
            db::eye::Object(
                db::TId(0),
                db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryEofMaxSpeed40, false}
            ),
            db::eye::ObjectLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::Detection(
                db::TId(0),
                db::eye::DetectedSign{
                    {100, 100, 200, 200},
                    traffic_signs::TrafficSign::ProhibitoryEofMaxSpeed40,
                    0.9,
                    false,
                    0.95
                }
            ),
            db::eye::DetectionGroup(
                db::TId(0),
                db::eye::DetectionType::Sign
            ),
            db::eye::Frame(
                db::TId(0),
                identical,
                makeUrlContext(1, "cw0"),
                {1920, 1080},
                time()
            ),
            db::eye::FrameLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::FramePrivacy(
                db::TId(0), db::FeaturePrivacy::Public
            )
        }
    });

    std::stringstream ss;
    json::Builder builder(ss);
    builder << [&](json::ArrayBuilder objects) {
        setObjects(context, objects);
    };
    json::Value result = json::Value::fromString(ss.str());

    json::Value expected = json::Value::fromString(R"(
        [
            {
                "geometry" : {"coordinates" : [0, 0], "type":  "Point"},
                "heading" : 0,
                "id" : "0",
                "type" : "prohibitory_eof_max_speed_40"
            }
        ]
    )");

    EXPECT_EQ(result, expected);
}

TEST(set_object_attrs_tests, set_road_marking_attrs_test)
{
    HypothesisContext context({
        {
            db::eye::Object(
                db::TId(0),
                db::eye::RoadMarkingAttrs{traffic_signs::TrafficSign::PrescriptionLaneDirectionF}
            ),
            db::eye::ObjectLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::Detection(
                db::TId(0),
                db::eye::DetectedRoadMarking{
                    {100, 100, 200, 200},
                    traffic_signs::TrafficSign::PrescriptionLaneDirectionF,
                    0.9
                }
            ),
            db::eye::DetectionGroup(
                db::TId(0),
                db::eye::DetectionType::RoadMarking
            ),
            db::eye::Frame(
                db::TId(0),
                identical,
                makeUrlContext(1, "cw0"),
                {1920, 1080},
                time()
            ),
            db::eye::FrameLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::FramePrivacy(
                db::TId(0), db::FeaturePrivacy::Public
            )
        }
    });

    std::stringstream ss;
    json::Builder builder(ss);
    builder << [&](json::ArrayBuilder objects) {
        setObjects(context, objects);
    };
    json::Value result = json::Value::fromString(ss.str());

    json::Value expected = json::Value::fromString(R"(
        [
            {
                "geometry" : {"coordinates" : [0, 0], "type":  "Point"},
                "heading" : 0,
                "id" : "0",
                "type" : "prescription_lane_direction_f"
            }
        ]
    )");

    EXPECT_EQ(result, expected);
}


TEST(set_object_attrs_tests, set_traffic_light_attrs_test)
{
    HypothesisContext context({
        {
            db::eye::Object(
                db::TId(0),
                db::eye::TrafficLightAttrs()
            ),
            db::eye::ObjectLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::Detection(
                db::TId(0),
                db::eye::DetectedTrafficLight{
                    {100, 100, 200, 200}, 0.9
                }
            ),
            db::eye::DetectionGroup(
                db::TId(0),
                db::eye::DetectionType::TrafficLight
            ),
            db::eye::Frame(
                db::TId(0),
                identical,
                makeUrlContext(1, "cw0"),
                {1920, 1080},
                time()
            ),
            db::eye::FrameLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::FramePrivacy(
                db::TId(0), db::FeaturePrivacy::Public
            )
        }
    });

    std::stringstream ss;
    json::Builder builder(ss);
    builder << [&](json::ArrayBuilder objects) {
        setObjects(context, objects);
    };
    json::Value result = json::Value::fromString(ss.str());

    json::Value expected = json::Value::fromString(R"(
        [
            {
                "geometry" : {"coordinates" : [0, 0], "type" : "Point"},
                "heading" : 0,
                "id" : "0"
            }
        ]
    )");

    EXPECT_EQ(result, expected);
}

TEST(set_object_attrs_tests, set_house_number_attrs_test)
{
    HypothesisContext context({
        {
            db::eye::Object(
                db::TId(0),
                db::eye::HouseNumberAttrs{"22"}
            ),
            db::eye::ObjectLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::Detection(
                db::TId(0),
                db::eye::DetectedHouseNumber{
                    {100, 100, 200, 200}, 0.9, "22"
                }
            ),
            db::eye::DetectionGroup(
                db::TId(0),
                db::eye::DetectionType::HouseNumber
            ),
            db::eye::Frame(
                db::TId(0),
                identical,
                makeUrlContext(1, "cw0"),
                {1920, 1080},
                time()
            ),
            db::eye::FrameLocation(
                db::TId(0u),
                geolib3::Point2(0., 0.),
                toRotation(geolib3::Heading(0.0), identical)
            ),
            db::eye::FramePrivacy(
                db::TId(0), db::FeaturePrivacy::Public
            )
        }
    });

    std::stringstream ss;
    json::Builder builder(ss);
    builder << [&](json::ArrayBuilder objects) {
        setObjects(context, objects);
    };
    json::Value result = json::Value::fromString(ss.str());

    json::Value expected = json::Value::fromString(R"(
        [
            {
                "geometry" : {"coordinates" : [0, 0], "type" : "Point"},
                "heading" : 0,
                "id" : "0",
                "number" : "22"
            }
        ]
    )");

    EXPECT_EQ(result, expected);
}

} // namespace maps::mrc::eye::tests
