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

hub.exec.boto3.client.ec2.create_nat_gateway
hub.exec.boto3.client.ec2.delete_nat_gateway
hub.exec.boto3.client.ec2.describe_nat_gateways
"""
from collections import OrderedDict
from typing import Any
from typing import Dict
from typing import List

__contracts__ = ["resource"]
TREQ = {
    "present": {
        "require": ["aws.ec2.subnet.present"],
    },
}


async def present(
    hub,
    ctx,
    name: str,
    subnet_id: str,
    connectivity_type: str,
    client_token: str = None,
    allocation_id: str = None,
    tags: List = None,
) -> Dict[str, Any]:
    r"""
    **Autogenerated function**

    Creates a NAT gateway in the specified subnet. This action creates a network interface in the specified subnet
    with a private IP address from the IP address range of the subnet. You can create either a public NAT gateway or
    a private NAT gateway. With a public NAT gateway, internet-bound traffic from a private subnet can be routed to
    the NAT gateway, so that instances in a private subnet can connect to the internet. With a private NAT gateway,
    private communication is routed across VPCs and on-premises networks through a transit gateway or virtual
    private gateway. Common use cases include running large workloads behind a small pool of allowlisted IPv4
    addresses, preserving private IPv4 addresses, and communicating between overlapping networks. For more
    information, see NAT gateways in the Amazon Virtual Private Cloud User Guide.

    Args:
        name(Text): The ID of the NAT gateway.
        subnet_id(Text): The subnet in which to create the NAT gateway.
        client_token(Text, optional): Unique, case-sensitive identifier that you provide to ensure the idempotency of the request. Constraint: Maximum 64 ASCII characters. This field is autopopulated if not provided.
        connectivity_type(Text, optional): Indicates whether the NAT gateway supports public or private connectivity. The default is public connectivity.
        allocation_id(Text, optional): [Public NAT gateway only]. The allocation ID of the Elastic IP address that's associated with the NAT gateway.
        tags(List, optional): The tags to assign to the subnet. Defaults to None.
            * Key (string) --  The key of the tag. Tag keys are case-sensitive and accept a maximum of 127 Unicode characters. May not begin with aws: .
            * Value (string) -- The value of the tag. Tag values are case-sensitive and accept a maximum of 255 Unicode characters.

    Request Syntax:
        [nat_gateway-id]:
          aws.ec2.nat_gateway.present:
          - subnet_id: 'string'
          - client_token: 'string'
          - connectivity_type: 'string'
          - allocation_id: 'string'
          - tags:
            - Key: 'string'
              Value: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            nat-0e7969ddf4c38831f:
              aws.ec2.nat_gateway.present:
                - subnet_id: subnet-026542dd856a97e15
                - client-token: nat-0e7969ddf4c38831f
                - connectivity_type: private
                - tags:
                  - Key: Name
                    Value: test-nat-gateway
    """

    result = dict(comment="", old_state=None, new_state=None, name=name, result=True)
    nat_gateway_id = None
    before = await hub.exec.boto3.client.ec2.describe_nat_gateways(
        ctx, NatGatewayIds=[name]
    )
    if before["result"] and before["ret"].get("NatGateways"):
        # check if tags need to be updated
        if tags is not None:
            nat_gateway_id = name
            update_ret = await hub.exec.aws.ec2.tag.update_tags(
                ctx=ctx,
                resource_id=name,
                old_tags=before["ret"]["NatGateways"][0]["Tags"],
                new_tags=tags,
            )
            result["comment"] = f"'{name}' already present. Updating tags"
            if not update_ret["result"]:
                result["comment"] = update_ret["comment"]
                result["result"] = False
    else:
        try:
            ret = await hub.exec.boto3.client.ec2.create_nat_gateway(
                ctx,
                AllocationId=allocation_id,
                ClientToken=client_token,
                SubnetId=subnet_id,
                TagSpecifications=[{"ResourceType": "natgateway", "Tags": tags}]
                if tags is not None
                else None,
                ConnectivityType=connectivity_type,
            )
            result["result"] = ret["ret"]
            if not result["result"]:
                result["comment"] = ret["comment"]
                return result
            nat_gateway_id = ret["ret"]["NatGateway"]["NatGatewayId"]
            result["comment"] = f"Created '{nat_gateway_id}'"
        except hub.tool.boto3.exception.ClientError as e:
            result["comment"] = f"{e.__class__.__name__}: {e}"
    after = None
    if nat_gateway_id is not None:
        after = await hub.exec.boto3.client.ec2.describe_nat_gateways(
            ctx, NatGatewayIds=[nat_gateway_id]
        )
    if before["result"] and before["ret"].get("NatGateways"):
        result["old_state"] = before["ret"]["NatGateways"][0]
    if after and after["result"] and after["ret"].get("NatGateways"):
        result["new_state"] = after["ret"]["NatGateways"][0]
    return result


async def absent(hub, ctx, name: str) -> Dict[str, Any]:
    r"""
    **Autogenerated function**

    Deletes the specified NAT gateway. Deleting a public NAT gateway disassociates its Elastic IP address, but does
    not release the address from your account. Deleting a NAT gateway does not delete any NAT gateway routes in your
    route tables.

    Args:
        name(Text): The ID of the NAT gateway.

    Request Syntax:
        [nat_gateway-id]:
          aws.ec2.nat_gateway.absent:
          - name: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            nat-0e7969ddf4c38831f:
                aws.ec2.nat_gateway.absent:
                  - name: nat-0e7969ddf4c38831f
    """

    result = dict(comment="", old_state=None, new_state=None, name=name, result=True)
    nat_gateway_id_list = [name]
    before = await hub.exec.boto3.client.ec2.describe_nat_gateways(
        ctx, NatGatewayIds=nat_gateway_id_list
    )
    if not before["result"]:
        result["comment"] = f"'{name}' already absent"
    else:
        try:
            if before["ret"]["NatGateways"][0]["State"] == "deleted":
                result["comment"] = f"'{name}' is already in deleted state."
            else:
                ret = await hub.exec.boto3.client.ec2.delete_nat_gateway(
                    ctx, NatGatewayId=name
                )
                result["result"] = ret["result"]
                if not result["result"]:
                    result["comment"] = ret["comment"]
                    return result
                result["comment"] = f"Deleted '{name}'"
        except hub.tool.boto3.exception.ClientError as e:
            result["comment"] = f"{e.__class__.__name__}: {e}"

    if before["result"] and before["ret"].get("NatGateways"):
        result["old_state"] = before["ret"]["NatGateways"][0]
    return result


async def describe(hub, ctx) -> Dict[str, Dict[str, Any]]:
    r"""
    **Autogenerated function**

    Describe the resource in a way that can be recreated/managed with the corresponding "present" function


    Describes one or more of your NAT gateways.


    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: bash

            $ idem describe aws.ec2.nat_gateway
    """
    result = {}

    ret = await hub.exec.boto3.client.ec2.describe_nat_gateways(ctx)
    if not ret["result"]:
        hub.log.debug(f"Could not describe nat_gateway {ret['comment']}")
        return result

    describe_parameters = OrderedDict(
        {
            "SubnetId": "subnet_id",
            "ConnectivityType": "connectivity_type",
            "Tags": "tags",
        }
    )

    for nat_gateway in ret["ret"]["NatGateways"]:
        nat_gateway_id = nat_gateway.get("NatGatewayId")
        resource_translated = []
        for parameter_old_key, parameter_new_key in describe_parameters.items():
            if (
                nat_gateway.get(parameter_old_key)
                and nat_gateway.get(parameter_old_key) is not None
            ):
                resource_translated.append(
                    {parameter_new_key: nat_gateway.get(parameter_old_key)}
                )
        if nat_gateway.get("NatGatewayAddresses"):
            for nat_gateway_address in nat_gateway.get("NatGatewayAddresses"):
                if "AllocationId" in nat_gateway_address:
                    resource_translated.append(
                        {"allocation_id": nat_gateway_address.get("AllocationId")}
                    )
                    break
        result[nat_gateway_id] = {"aws.ec2.nat_gateway.present": resource_translated}
    return result
