"""
generated by json2python-models v0.3.0 at Wed Feb 14 14:19:14 2024
command: /home/lundberg/python-environments/python-fido-mds/bin/json2models -m FidoMD metadata.json -f pydantic --datetime --max-strings-literals 0
"""

from datetime import datetime
from enum import Enum
from typing import List, Optional, Union

from pydantic import BaseModel, Field, field_validator


def date2datetime(value: str) -> datetime:
    return datetime.fromisoformat(value)


class AuthenticatorStatus(str, Enum):
    NOT_FIDO_CERTIFIED = "NOT_FIDO_CERTIFIED"
    FIDO_CERTIFIED = "FIDO_CERTIFIED"
    USER_VERIFICATION_BYPASS = "USER_VERIFICATION_BYPASS"
    ATTESTATION_KEY_COMPROMISE = "ATTESTATION_KEY_COMPROMISE"
    USER_KEY_REMOTE_COMPROMISE = "USER_KEY_REMOTE_COMPROMISE"
    USER_KEY_PHYSICAL_COMPROMISE = "USER_KEY_PHYSICAL_COMPROMISE"
    UPDATE_AVAILABLE = "UPDATE_AVAILABLE"
    REVOKED = "REVOKED"
    SELF_ASSERTION_SUBMITTED = "SELF_ASSERTION_SUBMITTED"
    FIDO_CERTIFIED_L1 = "FIDO_CERTIFIED_L1"
    FIDO_CERTIFIED_L1plus = "FIDO_CERTIFIED_L1plus"
    FIDO_CERTIFIED_L2 = "FIDO_CERTIFIED_L2"
    FIDO_CERTIFIED_L2plus = "FIDO_CERTIFIED_L2plus"
    FIDO_CERTIFIED_L3 = "FIDO_CERTIFIED_L3"
    FIDO_CERTIFIED_L3plus = "FIDO_CERTIFIED_L3plus"


class Algorithm(BaseModel):
    type_: str = Field(..., alias="type")
    alg: int


class AlternativeDescription(BaseModel):
    uk_ua: Optional[str] = Field(None, alias="uk-UA")
    de_de: Optional[str] = Field(None, alias="de-DE")
    fr_ca: Optional[str] = Field(None, alias="fr-CA")
    zh_cn: Optional[str] = Field(None, alias="zh-CN")
    zh_tw: Optional[str] = Field(None, alias="zh-TW")
    ru_ru: Optional[str] = Field(None, alias="ru-RU")
    fr_fr: Optional[str] = Field(None, alias="fr-FR")
    ko_kr: Optional[str] = Field(None, alias="ko-KR")
    en_us: Optional[str] = Field(None, alias="en-US")
    fr: Optional[str] = None


class Option(BaseModel):
    rk: Optional[bool] = None
    client_pin: Optional[bool] = Field(None, alias="clientPin")
    up: Optional[bool] = None
    uv: Optional[bool] = None
    user_verification_mgmt_preview: Optional[bool] = Field(None, alias="userVerificationMgmtPreview")
    credential_mgmt_preview: Optional[bool] = Field(None, alias="credentialMgmtPreview")
    plat: Optional[bool] = None
    bio_enroll: Optional[bool] = Field(None, alias="bioEnroll")
    uv_bio_enroll: Optional[bool] = Field(None, alias="uvBioEnroll")
    cred_mgmt: Optional[bool] = Field(None, alias="credMgmt")
    large_blobs: Optional[bool] = Field(None, alias="largeBlobs")
    ep: Optional[bool] = None
    authnr_cfg: Optional[bool] = Field(None, alias="authnrCfg")
    set_min_pin_length: Optional[bool] = Field(None, alias="setMinPINLength")
    always_uv: Optional[bool] = Field(None, alias="alwaysUv")
    pin_uv_auth_token: Optional[bool] = Field(None, alias="pinUvAuthToken")
    make_cred_uv_not_rqd: Optional[bool] = Field(None, alias="makeCredUvNotRqd")
    no_mc_ga_permissions_with_client_pin: Optional[bool] = Field(None, alias="noMcGaPermissionsWithClientPin")
    uv_acfg: Optional[bool] = Field(None, alias="uvAcfg")


class Certification(BaseModel):
    fido: Optional[int] = Field(None, alias="FIDO")
    fipscmvp2: Optional[int] = Field(None, alias="FIPS-CMVP-2")
    fipscmvp2_phy: Optional[int] = Field(None, alias="FIPS-CMVP-2-PHY")


class AuthenticatorGetInfo(BaseModel):
    versions: List[str]
    aaguid: str
    extensions: Optional[List[str]] = []
    options: Optional["Option"] = None
    max_msg_size: Optional[int] = Field(None, alias="maxMsgSize")
    pin_uv_auth_protocols: Optional[List[int]] = Field([], alias="pinUvAuthProtocols")
    max_credential_count_in_list: Optional[int] = Field(None, alias="maxCredentialCountInList")
    max_credential_id_length: Optional[int] = Field(None, alias="maxCredentialIdLength")
    transports: Optional[List[str]] = []
    algorithms: Optional[List["Algorithm"]] = []
    firmware_version: Optional[int] = Field(None, alias="firmwareVersion")
    max_serialized_large_blob_array: Optional[int] = Field(None, alias="maxSerializedLargeBlobArray")
    force_pin_change: Optional[bool] = Field(None, alias="forcePINChange")
    min_pin_length: Optional[int] = Field(None, alias="minPINLength")
    max_cred_blob_length: Optional[int] = Field(None, alias="maxCredBlobLength")
    max_rpi_ds_for_set_min_pin_length: Optional[int] = Field(None, alias="maxRPIDsForSetMinPINLength")
    certifications: Optional["Certification"] = None
    remaining_discoverable_credentials: Optional[int] = Field(None, alias="remainingDiscoverableCredentials")
    preferred_platform_uv_attempts: Optional[int] = Field(None, alias="preferredPlatformUvAttempts")
    uv_modality: Optional[int] = Field(None, alias="uvModality")


class BaDesc(BaseModel):
    self_attested_frr: float = Field(..., alias="selfAttestedFRR")
    self_attested_far: float = Field(..., alias="selfAttestedFAR")
    max_templates: int = Field(..., alias="maxTemplates")
    max_retries: int = Field(..., alias="maxRetries")
    block_slowdown: int = Field(..., alias="blockSlowdown")


class CaDesc(BaseModel):
    base: int
    min_length: int = Field(..., alias="minLength")
    max_retries: int = Field(..., alias="maxRetries")
    block_slowdown: int = Field(..., alias="blockSlowdown")


class Upv(BaseModel):
    major: int
    minor: int


class PaDesc(BaseModel):
    min_complexity: int = Field(..., alias="minComplexity")
    max_retries: int = Field(..., alias="maxRetries")
    block_slowdown: int = Field(..., alias="blockSlowdown")


class UserVerificationDetail(BaseModel):
    user_verification_method: str = Field(..., alias="userVerificationMethod")
    ca_desc: Optional["CaDesc"] = Field(None, alias="caDesc")
    ba_desc: Optional["BaDesc"] = Field(None, alias="baDesc")
    pa_desc: Optional["PaDesc"] = Field(None, alias="paDesc")


class SupportedExtension(BaseModel):
    id_: str = Field(..., alias="id")
    fail_if_unknown: bool
    data: Optional[str] = None


class Plte(BaseModel):
    r: int
    g: int
    b: int


class TcDisplayPngCharacteristic(BaseModel):
    width: int
    height: int
    bit_depth: int = Field(..., alias="bitDepth")
    color_type: int = Field(..., alias="colorType")
    compression: int
    filter_: int = Field(..., alias="filter")
    interlace: int
    plte: Optional[List["Plte"]] = []


class MetadataStatement(BaseModel):
    legal_header: str = Field(..., alias="legalHeader")
    description: str
    authenticator_version: int = Field(..., alias="authenticatorVersion")
    protocol_family: str = Field(..., alias="protocolFamily")
    schema_: int = Field(..., alias="schema")
    upv: List["Upv"]
    authentication_algorithms: List[str] = Field(..., alias="authenticationAlgorithms")
    public_key_alg_and_encodings: List[str] = Field(..., alias="publicKeyAlgAndEncodings")
    attestation_types: List[str] = Field(..., alias="attestationTypes")
    user_verification_details: List[List["UserVerificationDetail"]] = Field(..., alias="userVerificationDetails")
    key_protection: List[str] = Field(..., alias="keyProtection")
    matcher_protection: List[str] = Field(..., alias="matcherProtection")
    attachment_hint: List[str] = Field(..., alias="attachmentHint")
    tc_display: List[str] = Field(..., alias="tcDisplay")
    attestation_root_certificates: List[str] = Field(..., alias="attestationRootCertificates")
    aaguid: Optional[str] = None
    crypto_strength: Optional[int] = Field(None, alias="cryptoStrength")
    icon: Optional[str] = None
    authenticator_get_info: Optional["AuthenticatorGetInfo"] = Field(None, alias="authenticatorGetInfo")
    is_key_restricted: Optional[bool] = Field(None, alias="isKeyRestricted")
    is_fresh_user_verification_required: Optional[bool] = Field(None, alias="isFreshUserVerificationRequired")
    supported_extensions: Optional[List["SupportedExtension"]] = Field([], alias="supportedExtensions")
    alternative_descriptions: Optional["AlternativeDescription"] = Field(None, alias="alternativeDescriptions")
    attestation_certificate_key_identifiers: Optional[List[str]] = Field(
        [], alias="attestationCertificateKeyIdentifiers"
    )
    aaid: Optional[str] = None
    tc_display_content_type: Optional[str] = Field(None, alias="tcDisplayContentType")
    tc_display_png_characteristics: Optional[List["TcDisplayPngCharacteristic"]] = Field(
        [], alias="tcDisplayPNGCharacteristics"
    )

    def get_user_verification_details(self) -> List["UserVerificationDetail"]:
        res: List["UserVerificationDetail"] = []
        for sub_list in self.user_verification_details:
            res.extend([uvd for uvd in sub_list])
        return res


class StatusReport(BaseModel):
    status: AuthenticatorStatus
    effective_date: datetime = Field(..., alias="effectiveDate")
    certification_descriptor: Optional[str] = Field(None, alias="certificationDescriptor")
    certificate_number: Optional[str] = Field(None, alias="certificateNumber")
    certification_policy_version: Optional[Union[float, str]] = Field(None, alias="certificationPolicyVersion")
    certification_requirements_version: Optional[Union[float, str]] = Field(
        None, alias="certificationRequirementsVersion"
    )
    url: Optional[str] = None

    # validators
    _effective_date_to_datetime = field_validator("effective_date", mode="before")(date2datetime)


class MetadataEntry(BaseModel):
    metadata_statement: "MetadataStatement" = Field(..., alias="metadataStatement")
    status_reports: List["StatusReport"] = Field(..., alias="statusReports")
    time_of_last_status_change: datetime = Field(..., alias="timeOfLastStatusChange")
    aaguid: Optional[str] = None
    attestation_certificate_key_identifiers: Optional[List[str]] = Field(
        [], alias="attestationCertificateKeyIdentifiers"
    )
    aaid: Optional[str] = None

    # validators
    _time_of_last_status_change_to_datetime = field_validator("time_of_last_status_change", mode="before")(
        date2datetime
    )

    def get_latest_status_report(self) -> "StatusReport":
        return max(self.status_reports, key=lambda sr: sr.effective_date)


class FidoMD(BaseModel):
    legal_header: str = Field(..., alias="legalHeader")
    no: int
    next_update: datetime = Field(..., alias="nextUpdate")
    entries: List["MetadataEntry"]

    # validators
    _next_update_to_datetime = field_validator("next_update", mode="before")(date2datetime)
