# generated by datamodel-codegen:
#   filename:  openapi.yaml
#   timestamp: 2023-08-03T18:47:00+00:00

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import (
    List,
    Optional,
)

from pydantic import (
    AnyUrl,
    BaseModel,
    Field,
)


class ServiceType(BaseModel):
    group: str = Field(
        ...,
        description="Namespace in reverse domain name format. Use `org.ga4gh` for implementations compliant with official GA4GH specifications. For services with custom APIs not standardized by GA4GH, or implementations diverging from official GA4GH specifications, use a different namespace (e.g. your organization's reverse domain name).",
        examples=["org.ga4gh"],
    )
    artifact: str = Field(
        ...,
        description="Name of the API or GA4GH specification implemented. Official GA4GH types should be assigned as part of standards approval process. Custom artifacts are supported.",
        examples=["beacon"],
    )
    version: str = Field(
        ...,
        description="Version of the API or specification. GA4GH specifications use semantic versioning.",
        examples=["1.0.0"],
    )


class Organization(BaseModel):
    name: str = Field(
        ..., description="Name of the organization responsible for the service", examples=["My organization"]
    )
    url: AnyUrl = Field(
        ..., description="URL of the website of the organization (RFC 3986 format)", examples=["https://example.com"]
    )


class Service(BaseModel):
    id: str = Field(
        ...,
        description="Unique ID of this service. Reverse domain name notation is recommended, though not required. The identifier should attempt to be globally unique so it can be used in downstream aggregator services e.g. Service Registry.",
        examples=["org.ga4gh.myservice"],
    )
    name: str = Field(..., description="Name of this service. Should be human readable.", examples=["My project"])
    type: ServiceType
    description: Optional[str] = Field(
        None,
        description="Description of the service. Should be human readable and provide information about the service.",
        examples=["This service provides..."],
    )
    organization: Organization = Field(..., description="Organization providing the service")
    contactUrl: Optional[AnyUrl] = Field(
        None,
        description="URL of the contact for the provider of this service, e.g. a link to a contact form (RFC 3986 format), or an email (RFC 2368 format).",
        examples=["mailto:support@example.com"],
    )
    documentationUrl: Optional[AnyUrl] = Field(
        None,
        description="URL of the documentation of this service (RFC 3986 format). This should help someone learn how to use your service, including any specifics required to access data, e.g. authentication.",
        examples=["https://docs.myservice.example.com"],
    )
    createdAt: Optional[datetime] = Field(
        None,
        description="Timestamp describing when the service was first deployed and available (RFC 3339 format)",
        examples=["2019-06-04T12:58:19Z"],
    )
    updatedAt: Optional[datetime] = Field(
        None,
        description="Timestamp describing when the service was last updated (RFC 3339 format)",
        examples=["2019-06-04T12:58:19Z"],
    )
    environment: Optional[str] = Field(
        None,
        description="Environment the service is running in. Use this to distinguish between production, development and testing/staging deployments. Suggested values are prod, test, dev, staging. However this is advised and not enforced.",
        examples=["test"],
    )
    version: str = Field(
        ...,
        description="Version of the service being described. Semantic versioning is recommended, but other identifiers, such as dates or commit hashes, are also allowed. The version should be changed whenever the service is updated.",
        examples=["1.0.0"],
    )


class Artifact(Enum):
    drs = "drs"


class Type(BaseModel):
    artifact: Artifact = Field(..., examples=["drs"])


class DrsService(BaseModel):
    type: Type


class Error(BaseModel):
    msg: Optional[str] = Field(None, description="A detailed error message.")
    status_code: Optional[int] = Field(
        None, description="The integer representing the HTTP status code (e.g. 200, 404)."
    )


class Checksum(BaseModel):
    checksum: str = Field(..., description="The hex-string encoded checksum for the data")
    type: str = Field(
        ...,
        description="The digest method used to create the checksum.\nThe value (e.g. `sha-256`) SHOULD be listed as `Hash Name String` in the https://www.iana.org/assignments/named-information/named-information.xhtml#hash-alg[IANA Named Information Hash Algorithm Registry]. Other values MAY be used, as long as implementors are aware of the issues discussed in https://tools.ietf.org/html/rfc6920#section-9.4[RFC6920].\nGA4GH may provide more explicit guidance for use of non-IANA-registered algorithms in the future. Until then, if implementers do choose such an algorithm (e.g. because it's implemented by their storage provider), they SHOULD use an existing standard `type` value such as `md5`, `etag`, `crc32c`, `trunc512`, or `sha1`.",
        examples=["sha-256"],
    )


class AccessURL(BaseModel):
    url: str = Field(..., description="A fully resolvable URL that can be used to fetch the actual object bytes.")
    headers: Optional[List[str]] = Field(
        None,
        description="An optional list of headers to include in the HTTP request to `url`. These headers can be used to provide auth tokens required to fetch the object bytes.",
        examples=["Authorization: Basic Z2E0Z2g6ZHJz"],
    )


class SupportedType(Enum):
    None_ = "None"
    BasicAuth = "BasicAuth"
    BearerAuth = "BearerAuth"
    PassportAuth = "PassportAuth"


class Authorizations(BaseModel):
    supported_types: Optional[List[SupportedType]] = Field(
        None,
        description="An Optional list of support authorization types. More than one can be supported and tried in sequence. Defaults to `None` if empty or missing.",
    )
    passport_auth_issuers: Optional[List[str]] = Field(
        None,
        description="If authorizations contain `PassportAuth` this is a required list of visa issuers (as found in a visa's `iss` claim) that may authorize access to this object. The caller must only provide passports that contain visas from this list. It is strongly recommended that the caller validate that it is appropriate to send the requested passport/visa to the DRS server to mitigate attacks by malicious DRS servers requesting credentials they should not have.",
    )
    bearer_auth_issuers: Optional[List[str]] = Field(
        None,
        description="If authorizations contain `BearerAuth` this is an optional list of issuers that may authorize access to this object. The caller must provide a token from one of these issuers. If this is empty or missing it assumed the caller knows which token to send via other means. It is strongly recommended that the caller validate that it is appropriate to send the requested token to the DRS server to mitigate attacks by malicious DRS servers requesting credentials they should not have.",
    )


class AccessMethodType(Enum):
    s3 = "s3"
    gs = "gs"
    ftp = "ftp"
    gsiftp = "gsiftp"
    globus = "globus"
    htsget = "htsget"
    https = "https"
    file = "file"


class AccessMethod(BaseModel):
    type: AccessMethodType = Field(..., description="Type of the access method.")
    access_url: Optional[AccessURL] = None
    access_id: Optional[str] = Field(
        None,
        description="An arbitrary string to be passed to the `/access` method to get an `AccessURL`. This string must be unique within the scope of a single object. Note that at least one of `access_url` and `access_id` must be provided.",
    )
    region: Optional[str] = Field(
        None,
        description="Name of the region in the cloud service provider that the object belongs to.",
        examples=["us-east-1"],
    )
    authorizations: Optional[Authorizations] = None


class ContentsObject(BaseModel):
    name: str = Field(
        ...,
        description="A name declared by the bundle author that must be used when materialising this object, overriding any name directly associated with the object itself. The name must be unique within the containing bundle. This string is made up of uppercase and lowercase letters, decimal digits, hyphen, period, and underscore [A-Za-z0-9.-_]. See http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_282[portable filenames].",
    )
    id: Optional[str] = Field(
        None,
        description="A DRS identifier of a `DrsObject` (either a single blob or a nested bundle). If this ContentsObject is an object within a nested bundle, then the id is optional. Otherwise, the id is required.",
    )
    drs_uri: Optional[List[str]] = Field(
        None,
        description="A list of full DRS identifier URI paths that may be used to obtain the object. These URIs may be external to this DRS instance.",
        examples=["drs://drs.example.org/314159"],
    )
    contents: Optional[List[ContentsObject]] = Field(
        None,
        description='If this ContentsObject describes a nested bundle and the caller specified "?expand=true" on the request, then this contents array must be present and describe the objects within the nested bundle.',
    )


class DrsObject(BaseModel):
    id: str = Field(..., description="An identifier unique to this `DrsObject`")
    name: Optional[str] = Field(
        None,
        description="A string that can be used to name a `DrsObject`.\nThis string is made up of uppercase and lowercase letters, decimal digits, hyphen, period, and underscore [A-Za-z0-9.-_]. See http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_282[portable filenames].",
    )
    self_uri: str = Field(
        ...,
        description="A drs:// hostname-based URI, as defined in the DRS documentation, that tells clients how to access this object.\nThe intent of this field is to make DRS objects self-contained, and therefore easier for clients to store and pass around.  For example, if you arrive at this DRS JSON by resolving a compact identifier-based DRS URI, the `self_uri` presents you with a hostname and properly encoded DRS ID for use in subsequent `access` endpoint calls.",
        examples=["drs://drs.example.org/314159"],
    )
    size: int = Field(
        ...,
        description="For blobs, the blob size in bytes.\nFor bundles, the cumulative size, in bytes, of items in the `contents` field.",
    )
    created_time: datetime = Field(
        ...,
        description="Timestamp of content creation in RFC3339.\n(This is the creation time of the underlying content, not of the JSON object.)",
    )
    updated_time: Optional[datetime] = Field(
        None,
        description="Timestamp of content update in RFC3339, identical to `created_time` in systems that do not support updates. (This is the update time of the underlying content, not of the JSON object.)",
    )
    version: Optional[str] = Field(
        None,
        description="A string representing a version.\n(Some systems may use checksum, a RFC3339 timestamp, or an incrementing version number.)",
    )
    mime_type: Optional[str] = Field(
        None, description="A string providing the mime-type of the `DrsObject`.", examples=["application/json"]
    )
    checksums: List[Checksum] = Field(
        ...,
        description="The checksum of the `DrsObject`. At least one checksum must be provided.\nFor blobs, the checksum is computed over the bytes in the blob.\nFor bundles, the checksum is computed over a sorted concatenation of the checksums of its top-level contained objects (not recursive, names not included). The list of checksums is sorted alphabetically (hex-code) before concatenation and a further checksum is performed on the concatenated checksum value.\nFor example, if a bundle contains blobs with the following checksums:\nmd5(blob1) = 72794b6d\nmd5(blob2) = 5e089d29\nThen the checksum of the bundle is:\nmd5( concat( sort( md5(blob1), md5(blob2) ) ) )\n= md5( concat( sort( 72794b6d, 5e089d29 ) ) )\n= md5( concat( 5e089d29, 72794b6d ) )\n= md5( 5e089d2972794b6d )\n= f7a29a04",
        min_length=1,
    )
    access_methods: Optional[List[AccessMethod]] = Field(
        None,
        description="The list of access methods that can be used to fetch the `DrsObject`.\nRequired for single blobs; optional for bundles.",
        min_length=1,
    )
    contents: Optional[List[ContentsObject]] = Field(
        None,
        description="If not set, this `DrsObject` is a single blob.\nIf set, this `DrsObject` is a bundle containing the listed `ContentsObject` s (some of which may be further nested).",
    )
    description: Optional[str] = Field(None, description="A human readable description of the `DrsObject`.")
    aliases: Optional[List[str]] = Field(
        None,
        description="A list of strings that can be used to find other metadata about this `DrsObject` from external metadata sources. These aliases can be used to represent secondary accession numbers or external GUIDs.",
    )


ContentsObject.model_rebuild()
