"""
Autogenerated using `pop-create-idem <https://gitlab.com/saltstack/pop/pop-create-idem>`__

hub.exec.boto3.client.apigatewayv2.create_domain_name
hub.exec.boto3.client.apigatewayv2.delete_domain_name
hub.exec.boto3.client.apigatewayv2.get_domain_name
hub.exec.boto3.client.apigatewayv2.get_domain_names
hub.exec.boto3.client.apigatewayv2.tag_resource
hub.exec.boto3.client.apigatewayv2.untag_resource
hub.exec.boto3.client.apigatewayv2.update_domain_name
"""
import copy
from dataclasses import field
from dataclasses import make_dataclass
from typing import Any
from typing import Dict
from typing import List

__contracts__ = ["resource"]


async def present(
    hub,
    ctx,
    name: str,
    resource_id: str = None,
    domain_name_configurations: List[
        make_dataclass(
            "DomainNameConfiguration",
            [
                ("ApiGatewayDomainName", str, field(default=None)),
                ("CertificateArn", str, field(default=None)),
                ("CertificateName", str, field(default=None)),
                ("CertificateUploadDate", str, field(default=None)),
                ("DomainNameStatus", str, field(default=None)),
                ("DomainNameStatusMessage", str, field(default=None)),
                ("EndpointType", str, field(default=None)),
                ("HostedZoneId", str, field(default=None)),
                ("SecurityPolicy", str, field(default=None)),
                ("OwnershipVerificationCertificateArn", str, field(default=None)),
            ],
        )
    ] = None,
    mutual_tls_authentication: make_dataclass(
        "MutualTlsAuthenticationInput",
        [
            ("TruststoreUri", str, field(default=None)),
            ("TruststoreVersion", str, field(default=None)),
        ],
    ) = None,
    tags: Dict = None,
) -> Dict[str, Any]:
    r"""
    Creates an API Gateway v2 domain name resource.

    Args:
        name(string): An Idem name of the resource. This is also used as the name of the domain name during resource creation.
        resource_id(string, optional): The domain name resource identifier in Amazon Web Services.
        domain_name_configurations(List, optional): The domain name configurations. Defaults to None.
            * (ApiGatewayDomainName, optional): A domain name for the API.
            * (CertificateArn, optional): An AWS-managed certificate that will be used by the edge-optimized endpoint for this domain
                name. AWS Certificate Manager is the only supported source.
            * (CertificateName, optional): The user-friendly name of the certificate that will be used by the edge-optimized endpoint for
                this domain name.
            * (CertificateUploadDate, optional): The timestamp when the certificate that was used by edge-optimized endpoint for this domain name
                was uploaded.
            * (DomainNameStatus, optional): The status of the domain name migration. The valid values are AVAILABLE, UPDATING,
                PENDING_CERTIFICATE_REIMPORT, and PENDING_OWNERSHIP_VERIFICATION. If the status is UPDATING, the
                domain cannot be modified further until the existing operation is complete. If it is AVAILABLE,
                the domain can be updated.
            * (DomainNameStatusMessage, optional): An optional text message containing detailed information about status of the domain name
            migration.
            * (EndpointType, optional): The endpoint type.
            * (HostedZoneId, optional): The Amazon Route 53 Hosted Zone ID of the endpoint.
            * (SecurityPolicy, optional): The Transport Layer Security (TLS) version of the security policy for this domain name. The
            valid values are TLS_1_0 and TLS_1_2.
            * (OwnershipVerificationCertificateArn, optional): The ARN of the public certificate issued by ACM to validate ownership of your custom domain.
                Only required when configuring mutual TLS and using an ACM imported or private CA certificate
                ARN as the regionalCertificateArn
        mutual_tls_authentication(Dict, optional): The mutual TLS authentication configuration for a custom domain name. Defaults to None.
            * (TruststoreUri, optional): An Amazon S3 URL that specifies the truststore for mutual TLS authentication, for example,
                s3://bucket-name/key-name. The truststore can contain certificates from public or private
                certificate authorities. To update the truststore, upload a new version to S3, and then update
                your custom domain name to use the new version. To update the truststore, you must have
                permissions to access the S3 object.
            * (TruststoreVersion, optional): The version of the S3 object that contains your truststore. To specify a version, you must have
                versioning enabled for the S3 bucket.
        tags(Dict, optional): The collection of tags associated with a domain name.

    Request Syntax:
        [idem_test_aws_apigatewayv2_domain_name]:
          aws.apigatewayv2.domain_name.present:
            - name: 'string'
            - domain_name_configurations: [
                {
                    'ApiGatewayDomainName': 'string',
                    'CertificateArn': 'string',
                    'CertificateName': 'string',
                    'CertificateUploadDate': datetime(2015, 1, 1),
                    'DomainNameStatus': 'AVAILABLE'|'UPDATING'|'PENDING_CERTIFICATE_REIMPORT'|'PENDING_OWNERSHIP_VERIFICATION',
                    'DomainNameStatusMessage': 'string',
                    'EndpointType': 'REGIONAL'|'EDGE',
                    'HostedZoneId': 'string',
                    'SecurityPolicy': 'TLS_1_0'|'TLS_1_2',
                    'OwnershipVerificationCertificateArn': 'string'
                }
            ]
            - mutual_tls_authentication: {
                'TruststoreUri': 'string',
                'TruststoreVersion': 'string
              }
            - tags: {
                'string': 'string'
              }

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_domain_name:
              aws.apigatewayv2.domain_name.present:
                - name: value
                - domain_name_configurations: [
                    {
                        'ApiGatewayDomainName': value,
                        'CertificateArn': 'value,
                        'CertificateName': 'value,
                        'CertificateUploadDate': value,
                        'DomainNameStatus': value,
                        'DomainNameStatusMessage': value,
                        'EndpointType': value,
                        'HostedZoneId': value,
                        'SecurityPolicy': value,
                        'OwnershipVerificationCertificateArn': value
                    }
                ]
                - mutual_tls_authentication: {
                    'TruststoreUri': 'string',
                    'TruststoreVersion': 'string
                }
                - tags: {
                    value: value
                }
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    before_ret = None
    resource_updated = False

    if resource_id:
        before_ret = await hub.exec.boto3.client.apigatewayv2.get_domain_name(
            ctx, DomainName=resource_id
        )
        if not before_ret["result"]:
            result["result"] = False
            result["comment"] = before_ret["comment"]
            return result

    if before_ret:
        result["comment"] = hub.tool.aws.comment_utils.already_exists_comment(
            resource_type="aws.apigatewayv2.domain_name", name=name
        )
        result[
            "old_state"
        ] = hub.tool.aws.apigatewayv2.domain_name.convert_raw_domain_name_to_present(
            raw_resource=before_ret.get("ret")
        )
        result["new_state"] = copy.deepcopy(result["old_state"])

        resource_parameters = {
            "DomainNameConfigurations": domain_name_configurations,
            "MutualTlsAuthentication": mutual_tls_authentication,
        }

        update_domain_name_ret = await hub.exec.aws.apigatewayv2.domain_name.update(
            ctx,
            resource_id=resource_id,
            raw_resource=before_ret.get("ret"),
            resource_parameters=resource_parameters,
        )
        result["comment"] = result["comment"] + update_domain_name_ret["comment"]
        if not update_domain_name_ret["result"]:
            result["result"] = False
            return result

        resource_updated = resource_updated or bool(update_domain_name_ret["ret"])
        if update_domain_name_ret["ret"] and ctx.get("test", False):
            result["new_state"].update(update_domain_name_ret["ret"])

        if tags is not None and tags != result["old_state"].get("tags"):
            resource_arn = hub.tool.aws.arn_utils.build_arn(
                partition="aws",
                service="apigateway",
                region=ctx["acct"]["region_name"],
                resource="/domainnames/" + resource_id,
            )
            update_tags_ret = await hub.exec.aws.apigatewayv2.tag.update_tags(
                ctx,
                resource_arn=resource_arn,
                old_tags=result["old_state"].get("tags", {}),
                new_tags=tags,
            )
            result["comment"] = result["comment"] + update_tags_ret["comment"]
            if not update_tags_ret["result"]:
                result["result"] = False
                return result

            resource_updated = resource_updated or bool(update_tags_ret["ret"])
            if update_tags_ret["ret"] and ctx.get("test", False):
                result["new_state"]["tags"] = update_tags_ret["ret"].get("tags")

        if resource_updated and ctx.get("test", False):
            return result
    else:
        if ctx.get("test", False):
            result[
                "new_state"
            ] = raw_resource = hub.tool.aws.test_state_utils.generate_test_state(
                enforced_state={},
                desired_state={
                    "domain_name_configurations": domain_name_configurations,
                    "name": name,
                    "mutual_tls_authentication": mutual_tls_authentication,
                    "tags": tags,
                },
            )
            result["comment"] = hub.tool.aws.comment_utils.would_create_comment(
                resource_type="aws.apigatewayv2.domain_name", name=name
            )
            return result

        create_ret = await hub.exec.boto3.client.apigatewayv2.create_domain_name(
            ctx,
            DomainName=name,
            DomainNameConfigurations=domain_name_configurations,
            MutualTlsAuthentication=mutual_tls_authentication,
            Tags=tags,
        )
        if not create_ret["result"]:
            result["result"] = False
            result["comment"] = create_ret["comment"]
            return result

        result["comment"] = hub.tool.aws.comment_utils.create_comment(
            resource_type="aws.apigatewayv2.domain_name", name=name
        )
        resource_id = create_ret["ret"]["DomainName"]

    if (not result["old_state"]) or resource_updated:
        after_ret = await hub.exec.boto3.client.apigatewayv2.get_domain_name(
            ctx, DomainName=resource_id
        )
        if not after_ret["result"]:
            result["result"] = False
            result["comment"] = result["comment"] + after_ret["comment"]
            return result

        result[
            "new_state"
        ] = hub.tool.aws.apigatewayv2.domain_name.convert_raw_domain_name_to_present(
            raw_resource=after_ret.get("ret")
        )

    return result


async def absent(hub, ctx, name: str, resource_id: str = None) -> Dict[str, Any]:
    r"""
    Deletes an API Gateway v2 domain name resource.

    Args:
        name(string): An Idem name of the resource.
        resource_id(string, optional): The domain name resource identifier in Amazon Web Services.
            Idem automatically considers this resource being absent if this field is not specified.

    Request syntax:
        [idem_test_aws_apigatewayv2_domain_name]:
          aws.apigatewayv2.domain_name.absent:
            - name: 'string'
            - resource_id: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_domain_name:
              aws.apigatewayv2.domain_name.absent:
                - name: value
                - resource_id: value
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    if not resource_id:
        result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
            resource_type="aws.apigatewayv2.domain_name", name=name
        )
        return result

    before_ret = await hub.exec.boto3.client.apigatewayv2.get_domain_name(
        ctx, DomainName=resource_id
    )
    if not before_ret["result"]:
        if "NotFoundException" not in str(before_ret["comment"][0]):
            result["result"] = False
            result["comment"] = before_ret["comment"]
        else:
            result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
                resource_type="aws.apigatewayv2.domain_name", name=name
            )
        return result

    result[
        "old_state"
    ] = hub.tool.aws.apigatewayv2.domain_name.convert_raw_domain_name_to_present(
        raw_resource=before_ret["ret"],
    )

    if ctx.get("test", False):
        result["comment"] = hub.tool.aws.comment_utils.would_delete_comment(
            resource_type="aws.apigatewayv2.domain_name", name=name
        )
        return result

    delete_ret = await hub.exec.boto3.client.apigatewayv2.delete_domain_name(
        ctx, DomainName=resource_id
    )
    if not delete_ret["result"]:
        result["result"] = False
        result["comment"] = delete_ret["comment"]
        return result

    result["comment"] = hub.tool.aws.comment_utils.delete_comment(
        resource_type="aws.apigatewayv2.domain_name", name=name
    )
    return result


async def describe(hub, ctx) -> Dict[str, Dict[str, Any]]:
    r"""
    Describe the resource in a way that can be recreated/managed with the corresponding "present" function

    Gets the API Gateway v2 domain name resources for an AWS account.

    Returns:
        Dict[str, Dict[str, Any]]

    Examples:

        .. code-block:: bash

            $ idem describe aws.apigatewayv2.domain_name
    """

    result = {}

    describe_ret = await hub.exec.boto3.client.apigatewayv2.get_domain_names(ctx)
    if not describe_ret["result"]:
        hub.log.debug(f"Could not describe domain names {describe_ret['comment']}")
        return result

    for domain_name in describe_ret["ret"]["Items"]:
        resource_translated = (
            hub.tool.aws.apigatewayv2.domain_name.convert_raw_domain_name_to_present(
                raw_resource=domain_name,
            )
        )

        result[resource_translated["name"]] = {
            "aws.apigatewayv2.domain_name.present": [
                {parameter_key: parameter_value}
                for parameter_key, parameter_value in resource_translated.items()
            ]
        }

    return result


async def search(hub, ctx, name, resource_id: str) -> Dict[str, Any]:
    r"""
    Use an un-managed API Gateway v2 domain_name resource as a data-source.

    Args:
        name(string): An Idem name of the resource.
        resource_id(string): The domain name resource identifier in Amazon Web Services.

    Request syntax:
        [idem_test_aws_apigatewayv2_domain_name]:
          aws.apigatewayv2.domain_name.search:
            - resource_id: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_apigatewayv2_domain_name:
              aws.apigatewayv2.domain_name.search:
                - resource_id: value
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    search_ret = await hub.exec.boto3.client.apigatewayv2.get_domain_name(
        ctx, DomainName=resource_id
    )
    if not search_ret["result"]:
        result["result"] = False
        if "NotFoundException" not in str(search_ret["comment"][0]):
            result["comment"] = search_ret["result"]
        else:
            result["comment"] = (
                f"Unable to find aws.apigatewayv2.domain_name resource with resource id '{resource_id}'",
            )
        return result

    result[
        "old_state"
    ] = hub.tool.aws.apigatewayv2.domain_name.convert_raw_domain_name_to_present(
        raw_resource=search_ret["ret"],
    )
    result["new_state"] = copy.deepcopy(result["old_state"])

    return result
