#include <library/cpp/testing/gtest/gtest.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/generate_traffic_sign/include/generator.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/location/include/rotation.h>
#include <maps/wikimap/mapspro/services/mrc/libs/object/include/mock_loader.h>
#include <maps/libs/geolib/include/test_tools/comparison.h>

namespace maps::mrc::eye {

namespace tests {

namespace {

static const std::string TIMESTAMP_FORMAT = "%Y-%m-%dT%H:%M:%S";

} // namespace

TEST(test_validate_traffic_sign, filter_test)
{
    db::eye::Objects objects{
        {
            db::TId(0u),
            db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryNoEntry, false}
        },
        {
            db::TId(1u),
            db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryNoEntry, true}
        },
        {
            db::TId(2u),
            db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryMaxWeight, false}
        },
        {
            db::TId(3u),
            db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryMaxSpeed20, false}
        },
        {
            db::TId(4u),
            db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryNoLeftTurn, false}
        },
        {
            db::TId(5u),
            db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryNoLeftTurn, true}
        },
    };

    objects = filterObjects<TrafficSignGeneratorImpl>(objects);

    EXPECT_EQ(objects.size(), 3u);
}

TEST(test_validate_traffic_sign, validate_prohibitory_no_entry_test)
{
    object::MockLoader loader;

    const db::eye::Object object(
        db::TId(0u),
        db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryNoEntry, false}
    );

    const db::eye::ObjectLocation location(
        db::TId(0u),
        geolib3::Point2(0, 0),
        toRotation(geolib3::Heading(0.0), common::ImageOrientation(common::Rotation::CW_0))
    );

    const db::eye::Objects slaveObjects{};

    const auto hypotheses = TrafficSignGeneratorImpl::validate(object, location, slaveObjects, loader);

    ASSERT_EQ(hypotheses.size(), 1u);

    EXPECT_EQ(
        hypotheses[0].attrs<db::eye::TrafficSignAttrs>().feedbackType,
        wiki::social::feedback::Type::OneWayTrafficSign
    );
    EXPECT_TRUE(
        geolib3::test_tools::approximateEqual(
            hypotheses[0].mercatorPos(),
            location.mercatorPos(),
            geolib3::EPS
        )
    );
}

TEST(test_validate_traffic_sign, validate_maneuver_wo_table_test)
{
    object::MockLoader loader;

    const db::eye::Object object(
        db::TId(0u),
        db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryNoRightTurn, false}
    );

    const db::eye::ObjectLocation location(
        db::TId(0u),
        geolib3::Point2(0, 0),
        toRotation(geolib3::Heading(0.0), common::ImageOrientation(common::Rotation::CW_0))
    );

    const auto hypotheses = TrafficSignGeneratorImpl::validate(object, location, {}, loader);

    ASSERT_EQ(hypotheses.size(), 0u);
}

TEST(test_validate_traffic_sign, validate_maneuver_with_table_test)
{
    object::MockLoader loader;

    const db::eye::Object object(
        db::TId(0u),
        db::eye::SignAttrs{traffic_signs::TrafficSign::ProhibitoryNoRightTurn, false}
    );

    const db::eye::ObjectLocation location(
        db::TId(0u),
        geolib3::Point2(0, 0),
        toRotation(geolib3::Heading(0.0), common::ImageOrientation(common::Rotation::CW_0))
    );

    const db::eye::Objects slaveObjects{
        {
            db::TId(1u),
            db::eye::SignAttrs{traffic_signs::TrafficSign::InformationHeavyVehicle, false}
        },
    };

    const auto hypotheses = TrafficSignGeneratorImpl::validate(object, location, slaveObjects, loader);

    ASSERT_EQ(hypotheses.size(), 1u);

    EXPECT_EQ(
        hypotheses[0].attrs<db::eye::TrafficSignAttrs>().feedbackType,
        wiki::social::feedback::Type::TrucksManeuverRestrictionSign
    );
    EXPECT_TRUE(
        geolib3::test_tools::approximateEqual(
            hypotheses[0].mercatorPos(),
            location.mercatorPos(),
            geolib3::EPS
        )
    );
}

} //namespace tests

} //namespace maps::mrc::eye
