"""Data types and operations from Remote ID Display Data Observation 0.3.0 OpenAPI"""

# This file is autogenerated; do not modify manually!

from __future__ import annotations

from enum import Enum

from implicitdict import ImplicitDict

from uas_standards.utils import Operation

API_VERSION = "0.3.0"
"""Version of Remote ID Display Data Observation OpenAPI specification from which the objects in this package were generated."""


class UAType(str, Enum):
    """The UA Type can help infer performance, speed, and duration of flights, for example, a
    "fixed wing" can generally fly in a forward direction only (as compared to a multi-rotor).
    This can also help differentiate aircraft types without sharing operationally sensitive
    information like the make and model of a particular aircraft. Make and model are
    anticipated to become available during the Registration ID lookup process. UAS Type is also
    useful for correlating visual observation with data received. The types were formulated
    based on unique flight characteristics.

    `HybridLift` is a fixed wing aircraft that can take off vertically.  `Helicopter` includes multirotor.

    `VTOL` is equivalent to HybridLift, and kept for retro-compatibility with F3411-v19
    """

    NotDeclared = "NotDeclared"
    Aeroplane = "Aeroplane"
    Helicopter = "Helicopter"
    Gyroplane = "Gyroplane"
    VTOL = "VTOL"
    HybridLift = "HybridLift"
    Ornithopter = "Ornithopter"
    Glider = "Glider"
    Kite = "Kite"
    FreeBalloon = "FreeBalloon"
    CaptiveBalloon = "CaptiveBalloon"
    Airship = "Airship"
    FreeFallOrParachute = "FreeFallOrParachute"
    Rocket = "Rocket"
    TetheredPoweredAircraft = "TetheredPoweredAircraft"
    GroundObstacle = "GroundObstacle"
    Other = "Other"


TimestampAccuracy = float
"""Declaration of timestamp accuracy, which is the largest difference between Timestamp and true time of applicability for any of the following fields: Latitude, Longitude, Geodetic Altitude, Pressure Altitude of Position, Height. to determine time of applicability of the location data provided.  Expressed in seconds, precise to 1/10ths of seconds. The accuracy reflects the 95% uncertainty bound value for the timestamp."""


class RIDOperationalStatus(str, Enum):
    """Indicates operational status of associated aircraft."""

    Undeclared = "Undeclared"
    Ground = "Ground"
    Airborne = "Airborne"
    Emergency = "Emergency"
    RemoteIDSystemFailure = "RemoteIDSystemFailure"


RIDTrack = float
"""Direction of flight expressed as a "True North-based" ground track angle.  This value is provided in degrees East of North with a minimum resolution of 1 degree."""


RIDSpeed = float
"""Ground speed of flight in meters per second."""


class SpeedAccuracy(str, Enum):
    """Provides quality/containment on horizontal ground speed.

    `SAUnknown`: Unknown speed accuracy

    `SA10mpsPlus`: > 10 m/s

    `SA10mps`: < 10 m/s

    `SA3mps`: < 3 m/s

    `SA1mps`: < 1 m/s

    `SA03mps`: < 0.3 m/s
    """

    SAUnknown = "SAUnknown"
    SA10mpsPlus = "SA10mpsPlus"
    SA10mps = "SA10mps"
    SA3mps = "SA3mps"
    SA1mps = "SA1mps"
    SA03mps = "SA03mps"


VerticalSpeed = float
"""Speed up (vertically) WGS84-HAE, m/s"""


Longitude = float
"""Degrees of longitude east of the Prime Meridian, with reference to the WGS84 ellipsoid."""


Latitude = float
"""Degrees of latitude north of the equator, with reference to the WGS84 ellipsoid."""


class OperatorAltitudeAltitudeType(str, Enum):
    """Source of data for the altitude field."""

    Takeoff = "Takeoff"
    Dynamic = "Dynamic"
    Fixed = "Fixed"


Altitude = float
"""An altitude, in meters, above the WGS84 ellipsoid."""


class UAClassificationEUCategory(str, Enum):
    EUCategoryUndefined = "EUCategoryUndefined"
    Open = "Open"
    Specific = "Specific"
    Certified = "Certified"


class UAClassificationEUClass(str, Enum):
    EUClassUndefined = "EUClassUndefined"
    Class0 = "Class0"
    Class1 = "Class1"
    Class2 = "Class2"
    Class3 = "Class3"
    Class4 = "Class4"
    Class5 = "Class5"
    Class6 = "Class6"


UAClassificationEU = dict
"""Expected keys:
* category
* class
"""


class HorizontalAccuracy(str, Enum):
    """This is based on ADS-B NACp (plus the one extra increment).

    `HAUnknown`: Unknown horizontal accuracy

    `HA10NMPlus`: > 10NM (18.52km)

    `HA10NM`: < 10NM (18.52km)

    `HA4NM`: < 4NM (7.408km)

    `HA2NM`: < 2NM (3.704km)

    `HA1NM`: < 1NM (1852m)

    `HA05NM`: < 0.5NM (926m)

    `HA03NM`: < 0.3NM (555.6m)

    `HA01NM`: < 0.1NM (185.2m)

    `HA005NM`: < 0.05NM (92.6m)

    `HA30m`: < 30m

    `HA10m`: < 10m

    `HA3m`: < 3m

    `HA1m`: < 1m
    """

    HAUnknown = "HAUnknown"
    HA10NMPlus = "HA10NMPlus"
    HA10NM = "HA10NM"
    HA4NM = "HA4NM"
    HA2NM = "HA2NM"
    HA1NM = "HA1NM"
    HA05NM = "HA05NM"
    HA03NM = "HA03NM"
    HA01NM = "HA01NM"
    HA005NM = "HA005NM"
    HA30m = "HA30m"
    HA10m = "HA10m"
    HA3m = "HA3m"
    HA1m = "HA1m"


class VerticalAccuracy(str, Enum):
    """This is based on ADS-B Geodetic Vertical Accuracy (GVA) (plus the three extra increments)

    `VAUnknown`: Unknown vertical accuracy

    `VA150mPlus`: > 150m

    `VA150m`: < 150m

    `VA45m`: < 45m

    `VA25m`: < 25m

    `VA10m`: < 10m

    `VA3m`: < 3m

    `VA1m`: < 1m
    """

    VAUnknown = "VAUnknown"
    VA150mPlus = "VA150mPlus"
    VA150m = "VA150m"
    VA45m = "VA45m"
    VA25m = "VA25m"
    VA10m = "VA10m"
    VA3m = "VA3m"
    VA1m = "VA1m"


class AltitudeReference(str, Enum):
    W84 = "W84"
    EGM96 = "EGM96"
    EGM2008 = "EGM2008"
    Other = "Other"


class RIDHeightReference(str, Enum):
    """The reference datum above which the height is reported."""

    TakeoffLocation = "TakeoffLocation"
    GroundLevel = "GroundLevel"


class RIDHeight(ImplicitDict):
    """A relative altitude for the purposes of remote ID."""

    distance: float
    """Distance above reference datum.  This value is provided in meters and must have a minimum resolution of 1 meter."""

    reference: RIDHeightReference
    """The reference datum above which the height is reported."""


class CurrentState(ImplicitDict):
    """Current state of an aircraft."""

    timestamp: str | None
    """Time at which the message containing the current state information was generated by the display provider."""

    timestamp_accuracy: TimestampAccuracy | None

    operational_status: RIDOperationalStatus | None

    track: RIDTrack | None

    speed: RIDSpeed | None

    speed_accuracy: SpeedAccuracy | None
    """Accuracy of horizontal ground speed."""

    vertical_speed: VerticalSpeed | None


class UAS(ImplicitDict):
    """UAS information"""

    id: str | None
    """Observed arbitrary and format agnostic (string) identification of a UAS."""

    eu_classification: UAClassificationEU | None
    """When this field is specified, the Classification Type is "European Union".  If no other classification field is specified, the Classification Type is "Undeclared"."""


class LatLngPoint(ImplicitDict):
    """Point on the earth's surface."""

    lng: Longitude

    lat: Latitude


class OperatorAltitude(ImplicitDict):
    """Altitude associated with the Remote Pilot"""

    altitude: Altitude | None

    altitude_type: OperatorAltitudeAltitudeType | None
    """Source of data for the altitude field."""


class MSLAltitude(ImplicitDict):
    meters: float | None = 0
    """Height, in meters, above a mean sea level datum."""

    reference_datum: AltitudeReference | None


class Operator(ImplicitDict):
    """Operator's information"""

    id: str | None
    """CAA-issued registration/license ID for the remote pilot or operator."""

    location: LatLngPoint | None

    altitude: OperatorAltitude | None


class Position(ImplicitDict):
    """A position on Earth."""

    lat: Latitude

    lng: Longitude

    alt: Altitude | None

    accuracy_h: HorizontalAccuracy | None
    """Horizontal error that is likely to be present in this reported position."""

    accuracy_v: VerticalAccuracy | None
    """Vertical error that is likely to be present in this reported position."""

    msl_alt: MSLAltitude | None

    height: RIDHeight | None


class Path(ImplicitDict):
    """Path followed by a flight."""

    positions: list[Position]
    """Sequential positions available for a flight."""


class GetDetailsResponse(ImplicitDict):
    """Response to a request to get details about a flight."""

    operator: Operator | None

    uas: UAS | None


class Flight(ImplicitDict):
    id: str
    """Identifier of flight that may be used to obtain details about the flight. This is not necessarily the UTM/flight ID in the remote ID system."""

    aircraft_type: UAType | None
    """Aircraft type of the flight."""

    current_state: CurrentState | None

    most_recent_position: Position | None
    """Most recent position known for the flight."""

    recent_paths: list[Path] | None
    """Paths the flight recently traveled, if available."""


class Cluster(ImplicitDict):
    """A general area containing one or more flight."""

    corners: list[Position]
    """Two opposite corners of a rectangular lat-lng box bounding the cluster."""

    area_sqm: float
    """Area of the cluster in square meters."""

    number_of_flights: int
    """Number of flights within the cluster."""


class GetDisplayDataResponse(ImplicitDict):
    """Response to a request for current data that would be visualized by a Display Application."""

    flights: list[Flight] | None = []
    """Current information for set of discovered flights whose precise locations are known."""

    clusters: list[Cluster] | None = []
    """Current information for sets of discovered flights whose precise locations are not known."""


class OperationID(str, Enum):
    GetDisplayData = "getDisplayData"
    GetDetails = "getDetails"


OPERATIONS: dict[OperationID, Operation] = {
    OperationID.GetDisplayData: Operation(
        id="getDisplayData",
        path="/display_data",
        verb="GET",
        request_body_type=None,
        response_body_type={
            200: GetDisplayDataResponse,
        },
    ),
    OperationID.GetDetails: Operation(
        id="getDetails",
        path="/display_data/{id}",
        verb="GET",
        request_body_type=None,
        response_body_type={
            200: GetDetailsResponse,
            404: None,
        },
    ),
}
