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

hub.exec.boto3.client.elasticache.create_cache_subnet_group
hub.exec.boto3.client.elasticache.delete_cache_subnet_group
hub.exec.boto3.client.elasticache.describe_cache_subnet_groups
hub.exec.boto3.client.elasticache.modify_cache_subnet_group
"""
import copy
from collections import OrderedDict
from typing import Any
from typing import Dict
from typing import List


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


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

    Creates a new cache subnet group. Use cache subnet group parameter only when you are creating a cluster in an Amazon Virtual
    Private Cloud (Amazon VPC).

    Args:
        name(Text): A name, ID to identify the resource.
        cache_subnet_group_description(Text): Description of the cache subnet group
        subnet_ids(list): A list of VPC subnet IDs for the cache subnet group.
        tags(List, optional): A list of tags to be added to this resource.
            Key (string) - The key for the tag. May not be null.
            Value (string) - The tag's value. May be null.

    Request Syntax:
        [cache_subnet_group_name]:
          aws.elasticache.cache_subnet_group.present:
          - name: 'string'
          - cache_subnet_group_description: 'string'
          - subnet_ids: 'List'
          - tags:
            - Key: 'string'
              Value: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            cache_subnet_group_name:
              aws.elasticache.cache_subnet_group.present:
                - cache_subnet_group_description: "testing demo"
                - subnet_ids:
                    - subnet-239e4b44
                - tags:
                    - Key: Name
                      Value: test-elasticache
    """

    result = dict(comment="", name=name, old_state=None, new_state=None, result=True)
    update_new_state = True
    before = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
        ctx, CacheSubnetGroupName=name
    )
    try:
        if before["result"]:
            result["old_state"] = before["ret"]["CacheSubnetGroups"][0]
            result["comment"] = f"'{name}' already present."
            update_ret = (
                await hub.exec.boto3.client.elasticache.modify_cache_subnet_group(
                    ctx=ctx,
                    CacheSubnetGroupName=name,
                    CacheSubnetGroupDescription=cache_subnet_group_description,
                    SubnetIds=subnet_ids,
                )
            )
            if update_ret["result"]:
                result["comment"] = f"'Updated {name}'"
            else:
                update_new_state = False
                result["result"] = False
            resource_arn = before["ret"]["CacheSubnetGroups"][0]["ARN"]
            old_tags = await hub.exec.boto3.client.elasticache.list_tags_for_resource(
                ctx, ResourceName=resource_arn
            )
            if tags is not None and old_tags["ret"]["TagList"] != tags:
                # Update tags
                result["comment"] = f"'{name}' already present. Updating tags"
                update_new_state = True
                update_tag = await hub.exec.aws.elasticache.tag.update_tags(
                    ctx=ctx,
                    resource_arn=resource_arn,
                    old_tags=old_tags["ret"]["TagList"],
                    new_tags=tags,
                )
                if not update_tag["result"]:
                    result["comment"] = update_tag["comment"]
                    update_new_state = False
                    result["result"] = False
        else:
            ret = await hub.exec.boto3.client.elasticache.create_cache_subnet_group(
                ctx,
                CacheSubnetGroupName=name,
                CacheSubnetGroupDescription=cache_subnet_group_description,
                SubnetIds=subnet_ids,
                Tags=tags,
            )
            result["result"] = ret["result"]
            if not result["result"]:
                result["comment"] = ret["comment"]
                return result
            result["comment"] = f"Created '{name}'"
    except hub.tool.boto3.exception.ClientError as e:
        result["result"] = False
        result["comment"] = f"{e.__class__.__name__}: {e}"
    try:
        if update_new_state:
            after = (
                await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
                    ctx, CacheSubnetGroupName=name
                )
            )
            result["new_state"] = after["ret"]["CacheSubnetGroups"][0]
        else:
            result["new_state"] = copy.deepcopy(result["old_state"])
    except Exception as e:
        result["comment"] = str(e)
        result["result"] = False
    return result


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

    Deletes a cache subnet group.  You cannot delete a default cache subnet group or one that is associated with any
    clusters.

    Args:
        name(Text): A name, ID to identify the resource.

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            resource_is_absent:
              aws.elasticache.cache_subnet_group.absent:
                - name: value
    """

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

    before = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(
        ctx, CacheSubnetGroupName=name
    )
    if not before:
        result["comment"] = f"'{name}' already absent"
    elif ctx.get("test", False):
        result["comment"] = f"Would delete aws.elasticache.cache_subnet_group {name}"
        return result
    else:
        result["old_state"] = before["ret"]["CacheSubnetGroups"][0]
        try:
            ret = await hub.exec.boto3.client.elasticache.delete_cache_subnet_group(
                ctx, CacheSubnetGroupName=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}"
    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


    Returns a list of cache subnet group descriptions. If a subnet group name is specified, the list contains only
    the description of that group. This is applicable only when you have ElastiCache in VPC setup. All ElastiCache
    clusters now launch in VPC by default.


    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: bash

            $ idem describe aws.elasticache.cache_subnet_group
    """

    result = {}
    ret = await hub.exec.boto3.client.elasticache.describe_cache_subnet_groups(ctx)

    if not ret["result"]:
        hub.log.debug(f"Could not describe cache_subnet_group {ret['comment']}")
        return {}

    describe_parameters = OrderedDict(
        {
            "CacheSubnetGroupDescription": "cache_subnet_group_description",
        }
    )
    for subnet_group in ret["ret"]["CacheSubnetGroups"]:
        CacheSubnetGroupName = subnet_group.get("CacheSubnetGroupName")

        resource_translated = []
        for parameter_old_key, parameter_new_key in describe_parameters.items():
            if subnet_group.get(parameter_old_key) is not None:
                resource_translated.append(
                    {parameter_new_key: subnet_group.get(parameter_old_key)}
                )
        if subnet_group.get("Subnets"):
            subnet_ids_list = []
            for nat_gateway_address in subnet_group.get("Subnets"):
                if "SubnetIdentifier" in nat_gateway_address:
                    subnet_ids_list.append(nat_gateway_address.get("SubnetIdentifier"))
            resource_translated.append({"subnet_ids": subnet_ids_list})
        if subnet_group.get("ARN"):
            tags = await hub.exec.boto3.client.elasticache.list_tags_for_resource(
                ctx, ResourceName=subnet_group.get("ARN")
            )
            if tags["ret"]["TagList"]:
                resource_translated.append({"tags": tags["ret"]["TagList"]})
        result[CacheSubnetGroupName] = {
            "aws.elasticache.cache_subnet_group.present": resource_translated
        }
    return result
