"""Data types and operations from Remote ID Test Data Injection 0.5.1 OpenAPI"""

# This file is autogenerated; do not modify manually!

from __future__ import annotations

from enum import Enum

from implicitdict import ImplicitDict, StringBasedDateTime

from uas_standards.utils import Operation

API_VERSION = "0.5.1"
"""Version of Remote ID Test Data Injection OpenAPI specification from which the objects in this package were generated."""

RIDFlightID = str
"""ID, unique to a remote ID service provider, which identifies a particular flight for which the remote ID service provider is providing remote ID services.

The following characters are not allowed: \\0 \\t \\r \\n # % / : ? @ [ \\ ]
"""


class RIDAuthData(ImplicitDict):
    """Additional authentication data."""

    format: int | None = 0
    """Format of additional authentication data.

    0: None
    1: UAS ID Signature
    2: Operator ID Signature
    3: Message Set Signature
    4: Authentication Provided by Network Remote ID
    5: Specific Method
    6-9: Reserved for Spec
    10-15: Available for Private Use
    """

    data: str | None = ""
    """Authentication data in form specified by `format`."""


SpecificSessionID = str
"""A unique 20 byte ID intended to identify a specific flight (session) while providing a
greater level of privacy to the operator. The first byte is the registered unique Specific Session ID
Type maintained by a registrar (see Annex A5), and the remaining 19 bytes is the Session ID per the
Specific Session ID Type specification.

Initial scheme registry entries include:

0 – reserved
1 – Internet Engineering Task Force (IETF) Drone Remote Identification Protocol (DRIP) entity ID
2 – IEEE 1609.2 HashedID8

Expressed as a hexadecimal string of the underlying data bytes.  A recipient should ignore any dashes in this value.  If fewer than 20 bytes are specified, the remaining bytes at the end are assumed to have value 0.
"""


class UASID(ImplicitDict):
    """Identification of the UAS performing this flight.  At least one field of this object must be specified."""

    serial_number: str | None = ""
    """This is expressed in the CTA-2063-A Serial Number format."""

    registration_id: str | None = ""
    """If a CAA provides a method of registering UAS, this number is provided by the CAA or its authorized representative.  Format is <ICAO Nationality MarkA>.<CAA Assigned ID>, ASCII encoded, only uppercase letters (A-Z), dot (.), and digits (0-9) are allowed. Example is valid for the US."""

    utm_id: str | None = ""
    """A UTM-provided universally unique ID traceable to a non-obfuscated ID that acts as a "session id" to protect exposure of operationally sensitive information."""

    specific_session_id: SpecificSessionID | None


class TimeFormat(str, Enum):
    RFC3339 = "RFC3339"


class Time(ImplicitDict):
    value: StringBasedDateTime
    """RFC3339-formatted time/date string.  The time zone must be 'Z'."""

    format: TimeFormat = TimeFormat.RFC3339


class UserNotification(ImplicitDict):
    """Notification observed by virtual user."""

    observed_at: Time
    """Time at which the virtual user observed the notification."""

    message: str | None
    """Message presented to the user, description of notification, or other means of helping identify the nature of the notification, for the purpose of increased readability of test reports."""


class QueryUserNotificationsResponse(ImplicitDict):
    """Response object for query request for notifications observed by the virtual user."""

    user_notifications: list[UserNotification]
    """List of applicable observed user notifications."""


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


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


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


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 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"


OperatorId = str
"""CAA-issued registration/license ID for the remote pilot or operator. """


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

    lng: Longitude

    lat: Latitude


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

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


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

    altitude: Altitude | None

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


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
"""


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"""


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"


class RIDAircraftPosition(ImplicitDict):
    """Position of an aircraft as reported for remote ID purposes.
    The following fields are required for a successful injection, but are not included in the 'required' field to allow the uss_qualifier to check SP behavior in situations where a networked UAS would not provide the necessary data to participate in Network Remote ID:
    - lat - lng - alt
    """

    lat: Latitude | None

    lng: Longitude | None

    alt: Altitude | None

    height: RIDHeight | None

    accuracy_h: HorizontalAccuracy | None
    """Horizontal error that is likely to be present in this reported position.  Required when `extrapolated` field is true and always in the entry for the current state."""

    accuracy_v: VerticalAccuracy | None
    """Vertical error that is likely to be present in this reported position.  Required when `extrapolated` field is true and always in the entry for the current state."""

    extrapolated: bool | None
    """True if this position was generated primarily by computation rather than primarily from a direct instrument measurement.  Assumed false if not specified."""

    pressure_altitude: float | None
    """The uncorrected altitude (based on reference standard 29.92 inHg, 1013.25 mb) provides a reference for algorithms that utilize "altitude deltas" between aircraft.  This value is provided in meters and must have a minimum resolution of 1 meter."""


class RIDFlightDetails(ImplicitDict):
    """Details about a flight reported by a remote ID service provider.  At least one of the registration or serial fields must be filled if required by CAA."""

    id: str
    """ID for this flight, matching argument in request."""

    operator_id: OperatorId | None

    operator_location: LatLngPoint | None
    """Location of party controlling the aircraft."""

    operation_description: str | None
    """Free-text field that enables the operator to describe the purpose of a flight, if so desired."""

    auth_data: RIDAuthData | None

    serial_number: str | None
    """This field is DEPRECATED and will be removed in a future version; use uas_id.serial_number instead. Can be specified when no registration ID exists and required by law in a region. This is expressed in the ANSI/CTA-2063-A Physical Serial Number format."""

    registration_number: str | None
    """This field is DEPRECATED and will be removed in a future version; use uas_id.registration_number instead. If a CAA provides a method of registering UAS, this number is provided by the CAA or its authorized representative.  Required when required by law in a region."""

    uas_id: UASID | None

    operator_altitude: OperatorAltitude | None

    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 RIDRecentAircraftPosition(ImplicitDict):
    time: StringBasedDateTime
    """Time at which this position applied.  RFC 3339 format, per OpenAPI specification."""

    position: RIDAircraftPosition


class RIDAircraftState(ImplicitDict):
    """State of an aircraft for the purposes of remote ID.
    The following fields are required for a successful injection, but are not included in the 'required' field to allow the uss_qualifier to check SP behavior in situations where a networked UAS would not provide the necessary data to participate in Network Remote ID:
    - timestamp - timestamp_accuracy - accuracy_h - accuracy_v - speed - vertical_speed - track - speed_accuracy - position
    """

    timestamp: StringBasedDateTime | None
    """Time at which this state was valid.  This may be the time coming from the source, such as a GPS, or the time when the system computes the values using an algorithm such as an Extended Kalman Filter (EKF).  Timestamp must be expressed with a minimum resolution of 1/10th of a second.  RFC 3339 format, per OpenAPI specification."""

    timestamp_accuracy: TimestampAccuracy | None

    operational_status: RIDOperationalStatus | None

    position: RIDAircraftPosition | None

    track: RIDTrack | None

    speed: RIDSpeed | None

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

    vertical_speed: VerticalSpeed | None

    height: RIDHeight | None

    group_radius: float | None
    """Farthest horizontal distance from reported group location at which an aircraft in the group may be located (meters).  This value contains the "Operating Area Radius" data from the common data dictionary when group operation area is specified by point-radius."""

    group_ceiling: float | None
    """Maximum altitude (meters WGS84-HAE) of Group Operation.  This value contains the "Operating Area Ceiling" data from the common data dictionary when group operation area is specified by point-radius."""

    group_floor: float | None
    """Minimum altitude (meters WGS84-HAE) of Group Operation.  If not specified, ground level shall be assumed.  This value contains the "Operating Area Floor" data from the common data dictionary when group operation area is specified by point-radius."""

    group_count: int | None
    """When operating a group (or formation or swarm), number of aircraft in group.  This value contains the "Operating Area Count" data from the common data dictionary when group operation area is specified by point-radius."""

    group_time_start: StringBasedDateTime | None
    """Time at which a group operation starts.  This value contains the "Operation Area Start" data from the common data dictionary when group operation area is specified by point-radius."""

    group_time_end: StringBasedDateTime | None
    """Time at which a group operation starts.  This value contains the "Operation Area End" data from the common data dictionary when group operation area is specified by point-radius."""


class TestFlightDetails(ImplicitDict):
    """The set of data with which the Service Provider system under test should respond when queried for the details of a test flight."""

    effective_after: str
    """The time after which the Service Provider system under test should respond with `details`, unless other `details` with a more recent `effective_after` time (before the current time) are available."""

    details: RIDFlightDetails
    """The details of the flight. Follows the RIDFlightDetails schema from the ASTM remote ID standard."""


class TestFlight(ImplicitDict):
    """The set of data to be provided to a Service Provider's test data injector for a single flight."""

    injection_id: str
    """ID of the injected test flight.  Remains the same regardless of the flight ID/UTM ID reported in the system."""

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

    telemetry: list[RIDAircraftState]
    """The set of telemetry data that should be injected into the system for this flight. Each element follows the RIDAircraftState schema from the ASTM remote ID standard."""

    details_responses: list[TestFlightDetails]
    """The details of the flight as a function of time."""


class CreateTestParameters(ImplicitDict):
    """A complete set of data to be injected into a Service Provider system under test."""

    requested_flights: list[TestFlight]
    """One or more logical flights, each containing test data to inject into the system. Elements should be sorted in ascending order of `timestamp`."""


class ChangeTestResponse(ImplicitDict):
    injected_flights: list[TestFlight]
    """The complete set of test data actually injected into the Service Provider system under test."""

    version: str
    """Version of test.  Used to delete test."""


class DeleteTestResponse(ImplicitDict):
    injected_flights: list[TestFlight]
    """The complete set of test data deleted."""


class OperationID(str, Enum):
    CreateTest = "createTest"
    DeleteTest = "deleteTest"
    QueryUserNotifications = "QueryUserNotifications"


OPERATIONS: dict[OperationID, Operation] = {
    OperationID.CreateTest: Operation(
        id="createTest",
        path="/tests/{test_id}",
        verb="PUT",
        request_body_type=CreateTestParameters,
        response_body_type={
            200: ChangeTestResponse,
            409: None,
        },
    ),
    OperationID.DeleteTest: Operation(
        id="deleteTest",
        path="/tests/{test_id}/{version}",
        verb="DELETE",
        request_body_type=None,
        response_body_type={
            200: DeleteTestResponse,
        },
    ),
    OperationID.QueryUserNotifications: Operation(
        id="QueryUserNotifications",
        path="/user_notifications",
        verb="GET",
        request_body_type=None,
        response_body_type={
            200: QueryUserNotificationsResponse,
            400: None,
            401: None,
            403: None,
        },
    ),
}
