#include "../include/verification_policy.h"

#include <yandex/maps/mrc/traffic_signs/signs.h>
#include <maps/libs/common/include/environment.h>

#include <unordered_set>

namespace maps::mrc::eye {

namespace {

const std::unordered_set<traffic_signs::TrafficSign>
    MANEUVERS_AFFECTING_TRAFFIC_SIGNS{
        traffic_signs::TrafficSign::ProhibitoryNoEntry,
        traffic_signs::TrafficSign::ProhibitoryNoVehicles,
        traffic_signs::TrafficSign::ProhibitoryNoHeavyGoodsVehicles,
        traffic_signs::TrafficSign::ProhibitoryNoRightTurn,
        traffic_signs::TrafficSign::ProhibitoryNoLeftTurn,
        traffic_signs::TrafficSign::ProhibitoryNoUturn,
        traffic_signs::TrafficSign::ProhibitoryMaxWeight,
        traffic_signs::TrafficSign::ProhibitoryMaxWeightPerAxle,
        traffic_signs::TrafficSign::ProhibitoryMaxHeight,
        traffic_signs::TrafficSign::ProhibitoryMaxWidth,
        traffic_signs::TrafficSign::ProhibitoryMaxLength,
        traffic_signs::TrafficSign::MandatoryProceedStraight,
        traffic_signs::TrafficSign::MandatoryProceedStraightOrTurnLeft,
        traffic_signs::TrafficSign::MandatoryProceedStraightOrTurnRight,
        traffic_signs::TrafficSign::MandatoryRoundabout,
        traffic_signs::TrafficSign::MandatoryTurnLeft,
        traffic_signs::TrafficSign::MandatoryTurnLeftAhead,
        traffic_signs::TrafficSign::MandatoryTurnRight,
        traffic_signs::TrafficSign::MandatoryTurnRightAhead,
        traffic_signs::TrafficSign::MandatoryTurnRightOrLeft,
        traffic_signs::TrafficSign::MandatoryDrivingDirectionR,
        traffic_signs::TrafficSign::MandatoryDrivingDirectionL,
        traffic_signs::TrafficSign::MandatoryDrivingDirectionRL,
        traffic_signs::TrafficSign::PrescriptionOneWayRoad,
        traffic_signs::TrafficSign::PrescriptionEofOneWayRoad,
        traffic_signs::TrafficSign::PrescriptionEntryToOneWayRoadOnTheRight,
        traffic_signs::TrafficSign::PrescriptionEntryToOneWayRoadOnTheLeft,
        traffic_signs::TrafficSign::PrescriptionLanesDirection,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFL,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFR,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionF,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFl,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFr,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionL,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionRL,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionR,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionOther,
        traffic_signs::TrafficSign::PrescriptionStartNewLineRight,
        traffic_signs::TrafficSign::PrescriptionStartNewLineLeft,
        traffic_signs::TrafficSign::PrescriptionEndLineRight,
        traffic_signs::TrafficSign::PrescriptionEndLineLeft,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFFr,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFFl,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFrR,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionFrFl,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionB,
        traffic_signs::TrafficSign::PrescriptionLaneDirectionLFl,
    };

bool affectsManeuvers(const db::eye::SignAttrs& attrs)
{
    return MANEUVERS_AFFECTING_TRAFFIC_SIGNS.count(attrs.type);
}


} // namespace

VerificationRules loadVerificationRules()
{
    std::vector<VerificationRule> result;
    const auto environment = maps::common::getYandexEnvironment();
    if (environment == maps::common::Environment::Testing) {
        result.push_back(
            VerificationRule {
                .geoId = 20279, // Moscow CAO geoid
                .objectType = db::eye::ObjectType::Sign,
                .objectPredicate =
                    [](const db::eye::Object& object) {
                        return affectsManeuvers(object.attrs<db::eye::SignAttrs>());
                    },
                .verificationAction = {
                    .verifyObjectDetections = true,
                    .verifyObjectDuplication = true,
                    .verifyObjectMissingness = true }
            }
        );

    } else if (environment == maps::common::Environment::Stable) {
        result.push_back(
            VerificationRule {
                .geoId = 213, // Moscow 
                .objectType = db::eye::ObjectType::Sign,
                .objectPredicate =
                    [](const db::eye::Object& object) {
                        return affectsManeuvers(object.attrs<db::eye::SignAttrs>());
                    },
                .verificationAction = {
                    .verifyObjectDetections = true,
                    .verifyObjectDuplication = true,
                    .verifyObjectMissingness = true  }
            }
        );
    }
    return result;
}


VerificationAction merge(const VerificationAction& one, const VerificationAction& other)
{
    return VerificationAction{
        .verifyObjectDetections = one.verifyObjectDetections || other.verifyObjectDetections,
        .verifyObjectDuplication = one.verifyObjectDuplication || other.verifyObjectDuplication,
        .verifyObjectMissingness = one.verifyObjectMissingness || other.verifyObjectMissingness
    };
}

} // namespace maps::mrc::eye
