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

hub.exec.boto3.client.ec2.associate_route_table
hub.exec.boto3.client.ec2.create_route_table
hub.exec.boto3.client.ec2.delete_route_table
hub.exec.boto3.client.ec2.describe_route_tables
hub.exec.boto3.client.ec2.disassociate_route_table
resource = hub.tool.boto3.resource.create(ctx, "ec2", "RouteTable", name)
hub.tool.boto3.resource.exec(resource, associate_with_subnet, *args, **kwargs)
hub.tool.boto3.resource.exec(resource, create_route, *args, **kwargs)
hub.tool.boto3.resource.exec(resource, create_tags, *args, **kwargs)
hub.tool.boto3.resource.exec(resource, delete, *args, **kwargs)
"""
import copy
from typing import Any
from typing import Dict
from typing import List

__contracts__ = ["resource"]

TREQ = {
    "present": {
        "require": [
            "aws.ec2.vpc.present",
        ],
    },
}


async def present(
    hub,
    ctx,
    name: str,
    vpc_id: str,
    resource_id: str = None,
    associations: List = None,
    routes: List = None,
    propagating_vgws: List = None,
    tags: List = None,
) -> Dict[str, Any]:
    r"""
    **Autogenerated function**

    Creates a route table for the specified VPC. After you create a route table, you can add routes and associate
    the table with a subnet. For more information, see Route tables in the Amazon Virtual Private Cloud User Guide.

    Args:
        name(Text): An Idem name of the route table to create.
        resource_id(Text, optional): AWS Route Table ID
        vpc_id(Text): ID of the VPC.
        associations(list, optional): The associations between the route table and one or more subnets or a gateway.
            Defaults to None.
            * SubnetId (Text) -- The ID of the subnet. A subnet ID is not returned for an implicit association.
            * GatewayId (Text) -- The ID of the internet gateway or virtual private gateway.
        routes(list, optional): The routes in the route table.
            Defaults to None.
            DestinationCidrBlock (Text) -- The IPv4 CIDR block used for the destination match.
            DestinationIpv6CidrBlock (Text) -- The IPv6 CIDR block used for the destination match.
            DestinationPrefixListId (Text) -- The prefix of the Amazon Web Service.
            EgressOnlyInternetGatewayId (Text) -- The ID of the egress-only internet gateway.
            GatewayId (Text) -- The ID of a gateway attached to your VPC.
            InstanceId (Text) -- The ID of a NAT instance in your VPC.
            InstanceOwnerId (Text) -- The ID of Amazon Web Services account that owns the instance.
            NatGatewayId (Text) -- The ID of a NAT gateway.
            TransitGatewayId (Text) -- The ID of a transit gateway.
            LocalGatewayId (Text) -- The ID of the local gateway.
            CarrierGatewayId (Text) -- The ID of the carrier gateway.
            NetworkInterfaceId (Text) -- The ID of the network interface.
            VpcPeeringConnectionId (Text) -- The ID of a VPC peering connection.
            CoreNetworkArn (Text) -- The Amazon Resource Name (ARN) of the core network.
        propagating_vgws(list, optional): Any virtual private gateway (VGW) propagating routes.
            GatewayId (Text) -- The ID of the virtual private gateway.
        tags(List, optional): The tags to assign to the route_table. 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:
        [route_table-resource-name]:
          aws.ec2.route_table.present:
          - vpc_id: 'string'
          - resource_id: 'string'
          - associations:
            - GatewayId: 'string'
            - SubnetId: 'string'
          - routes:
            - DestinationCidrBlock: 'string'
              GatewayId: 'string'
          - propagating_vgws:
             - 'string'
          - tags:
            - Key: 'string'
              Value: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            test_route-table:
              aws.ec2.route_table.present:
              - vpc_id: vpc-02850adfa9f6fc916
              - resource_id: route_table-3485hydfe5f6tb998
              - associations:
                - GatewayId: vgw-0334141b528f99316
                - SubnetId: subnet-0610f7c1a12a1af6a
              - routes:
                - DestinationCidrBlock: 198.31.0.0/16
                  GatewayId: local
              - propagating_vgws:
                 - vgw-0334141b528f99316
              - tags:
                - Key: Name
                  Value: route-table-association-test
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)
    update_successful = False
    plan_state = {}
    before = None
    if resource_id:
        before = await hub.exec.boto3.client.ec2.describe_route_tables(
            ctx, RouteTableIds=[resource_id]
        )
    if before and before["result"]:
        try:
            result[
                "old_state"
            ] = hub.tool.aws.ec2.conversion_utils.convert_raw_route_table_to_present(
                resource=before["ret"].get("RouteTables")[0],
                idem_resource_name=name,
            )
            plan_state = copy.deepcopy(result["old_state"])
            route_table_resource = before["ret"].get("RouteTables")[0]
            update_ret = await hub.exec.aws.ec2.route_table.update_associations_routes(
                ctx=ctx,
                route_table_id=route_table_resource.get("RouteTableId"),
                old_routes=route_table_resource.get("Routes"),
                new_routes=routes,
                old_associations=route_table_resource.get("Associations"),
                new_associations=associations,
                old_propagating_vgws=route_table_resource.get("PropagatingVgws"),
                new_propagating_vgws=propagating_vgws,
            )
            result["comment"] = result["comment"] + update_ret["comment"]
            update_successful = update_ret["result"]
            if not update_ret["result"]:
                result["result"] = False
            if update_ret["ret"] and ctx.get("test", False):
                if update_ret["ret"].get("routes") is not None:
                    plan_state["routes"] = update_ret["ret"].get("routes")
                if update_ret["ret"].get("associations") is not None:
                    plan_state["associations"] = update_ret["ret"].get("associations")
                if update_ret["ret"].get("vgws") is not None:
                    plan_state["propagating_vgws"] = update_ret["ret"].get("vgws")
            if update_successful and tags is not None:
                # Update tags
                update_ret = await hub.exec.aws.ec2.tag.update_tags(
                    ctx=ctx,
                    resource_id=route_table_resource.get("RouteTableId"),
                    old_tags=route_table_resource.get("Tags"),
                    new_tags=tags,
                )
                result["comment"] = result["comment"] + update_ret["comment"]
                result["result"] = update_ret["result"]
                if (
                    ctx.get("test", False)
                    and update_ret["result"]
                    and update_ret["ret"] is not None
                ):
                    plan_state["tags"] = update_ret["ret"].get("tags")
        except hub.tool.boto3.exception.ClientError as e:
            result["comment"] = result["comment"] + (f"{e.__class__.__name__}: {e}",)
            result["result"] = False
    else:
        if ctx.get("test", False):
            result["new_state"] = hub.tool.aws.test_state_utils.generate_test_state(
                enforced_state={},
                desired_state={
                    "name": name,
                    "vpc_id": vpc_id,
                    "resource_id": name,
                    "associations": associations,
                    "routes": routes,
                    "propagating_vgws": propagating_vgws,
                    "tags": tags,
                },
            )
            result["comment"] = (f"Would create aws.ec2.route_table {name}",)
            return result
        try:
            ret = await hub.exec.boto3.client.ec2.create_route_table(
                ctx,
                TagSpecifications=[{"ResourceType": "route-table", "Tags": tags}]
                if tags
                else None,
                VpcId=vpc_id,
            )
            result["result"] = ret["ret"]
            if not result["result"]:
                result["comment"] = ret["comment"]
                result["result"] = False
                return result
            resource_id = ret["ret"]["RouteTable"]["RouteTableId"]
            result["comment"] = result["comment"] + (f"Created '{resource_id}'",)

            # Associate routes, associations and virtual gateways if provided
            update_ret = await hub.exec.aws.ec2.route_table.update_associations_routes(
                ctx=ctx,
                route_table_id=resource_id,
                old_routes=[],
                new_routes=routes,
                old_associations=[],
                new_associations=associations,
                old_propagating_vgws=[],
                new_propagating_vgws=propagating_vgws,
            )
            result["comment"] = result["comment"] + update_ret["comment"]
            result["result"] = result["result"] and update_ret["result"]
        except hub.tool.boto3.exception.ClientError as e:
            result["comment"] = result["comment"] + (f"{e.__class__.__name__}: {e}",)
            result["result"] = False
    try:
        if ctx.get("test", False):
            result["new_state"] = plan_state
        elif update_successful or not (before and before["result"]):
            after = await hub.exec.boto3.client.ec2.describe_route_tables(
                ctx, RouteTableIds=[resource_id]
            )
            result[
                "new_state"
            ] = hub.tool.aws.ec2.conversion_utils.convert_raw_route_table_to_present(
                resource=after["ret"].get("RouteTables")[0],
                idem_resource_name=name,
            )
        else:
            result["new_state"] = copy.deepcopy(result["old_state"])
    except Exception as e:
        result["comment"] = result["comment"] + (str(e),)
        result["result"] = False
    return result


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

    Deletes the specified route table. You must disassociate the route table from any subnets before you can delete
    it. You can't delete the main route table.

    Args:
        resource_id: (Text): The AWS ID of the EC2 Route Table
        name(Text): A name or ID to identify the resource.

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            resource_is_absent:
              aws.ec2.route_table.absent:
                - name: value
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)
    before = await hub.exec.boto3.client.ec2.describe_route_tables(
        ctx, RouteTableIds=[resource_id]
    )
    if not before["result"]:
        result["comment"] = (f"'{resource_id}' already absent",)
    else:
        result[
            "old_state"
        ] = hub.tool.aws.ec2.conversion_utils.convert_raw_route_table_to_present(
            resource=before["ret"]["RouteTables"][0],
            idem_resource_name=name,
        )
        if ctx.get("test", False):
            result["comment"] = (f"Would delete aws.ec2.route_table '{resource_id}'",)
            return result
        else:
            try:
                # we have to disassociate all subnets and gateways before we can delete route table
                if before["ret"] and before["ret"]["RouteTables"]:
                    old_route_table = before["ret"]["RouteTables"][0]
                    if old_route_table.get("Associations"):
                        for association in old_route_table.get("Associations"):
                            if association.get("Main") is not True:
                                ret = await hub.exec.boto3.client.ec2.disassociate_route_table(
                                    ctx,
                                    AssociationId=association.get(
                                        "RouteTableAssociationId"
                                    ),
                                )
                                if not ret.get("result"):
                                    result["comment"] = (
                                        result["comment"] + ret["comment"]
                                    )
                                    result["result"] = False
                                    return result
                ret = await hub.exec.boto3.client.ec2.delete_route_table(
                    ctx, RouteTableId=resource_id
                )
                result["result"] = ret["result"]
                if not result["result"]:
                    result["comment"] = result["comment"] + ret["comment"]
                    result["result"] = False
                    return result
                result["comment"] = result["comment"] + (f"Deleted '{resource_id}'",)
            except hub.tool.boto3.exception.ClientError as e:
                result["comment"] = 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


    Describes one or more of your route tables. Each subnet in your VPC must be associated with a route table. If a
    subnet is not explicitly associated with any route table, it is implicitly associated with the main route table.
    This command does not return the subnet ID for implicit associations. For more information, see Route tables in
    the Amazon Virtual Private Cloud User Guide.


    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: bash

            $ idem describe aws.ec2.route_table
    """

    result = {}
    ret = await hub.exec.boto3.client.ec2.describe_route_tables(ctx)
    if not ret["result"]:
        hub.log.debug(f"Could not describe route_table {ret['comment']}")
        return result
    for route_table in ret["ret"]["RouteTables"]:
        route_table_id = route_table.get("RouteTableId")
        resource_converted = (
            hub.tool.aws.ec2.conversion_utils.convert_raw_route_table_to_present(
                resource=route_table,
                idem_resource_name=route_table_id,
            )
        )
        result[route_table_id] = {"aws.ec2.route_table.present": [resource_converted]}
    return result
