"""Acceptance thresholds for the steering mode comparison scenarios."""
from abc import ABC, abstractmethod
import enum

ErrorType = enum.Enum(
    value="ErrorType",
    names=[
        ("Non-expected heading error diff(deg)", 0),
        ("NON_EXPECTED_HEADING_ERROR_DIFF", 0),
        ("Projected Lateral error(m)", 1),
        ("PROJECTED_LATERAL_ERROR", 1),
        ("Projected Velocity vx error(m/s)", 2),
        ("PROJECTED_VELOCITY_ERROR", 2),
    ],
)


class Threshold(ABC):
    @abstractmethod
    def name(self):
        pass

    @abstractmethod
    def decision_thresholds(self):
        return {
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 0,
            ErrorType.PROJECTED_LATERAL_ERROR: 0,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0,
        }

    def to_dict(self):
        d = {}
        decision_thresh = self.decision_thresholds()
        for key in decision_thresh:
            nested_key = (self.name(), "decision", key.name)
            d[nested_key] = decision_thresh[key]

        return d


class PedJaywalkerHandling(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:pedestrian_jaywalker_handling"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.05,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 0.3,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class FollowAgent(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:follow_agent"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.05,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 0.3,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class CutIn(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:cut_in"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.05,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 0.3,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class TrafficLightJunction(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:traffic_light_junction"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.06,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 0.3,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class NonTrafficLightJunction(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:non_traffic_light_junction"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.05,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 0.3,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class LaneChangeMerge(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:lane_change_merge"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.4,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 1.7,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class DoubleParkedVehicle(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:double_parked_vehicle"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.6,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 7.0,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class ScoopParking(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:scoop_parking"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.8,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 9.0,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.1,
        }


class GetOnRoad(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:get_on_road"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.8,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 10.0,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.12,
        }


class ConstructionZone(Threshold):
    def name(self):
        return "//log_tests/pisces/steering_mode:construction_zone"

    def decision_thresholds(self):
        return {
            ErrorType.PROJECTED_LATERAL_ERROR: 0.5,
            ErrorType.NON_EXPECTED_HEADING_ERROR_DIFF: 5.0,
            ErrorType.PROJECTED_VELOCITY_ERROR: 0.2,
        }


STEERING_MODE_SCENARIO_THRESHOLDS = {
    **PedJaywalkerHandling().to_dict(),
    **FollowAgent().to_dict(),
    **CutIn().to_dict(),
    **TrafficLightJunction().to_dict(),
    **NonTrafficLightJunction().to_dict(),
    **LaneChangeMerge().to_dict(),
    **DoubleParkedVehicle().to_dict(),
    **ScoopParking().to_dict(),
    **GetOnRoad().to_dict(),
    **ConstructionZone().to_dict(),
}
