#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

DOCUMENTATION = r"""
---
module: dms_replication_subnet_group
version_added: 1.0.0
short_description: creates or destroys a data migration services subnet group
description:
    - Creates or destroys a data migration services subnet group.
options:
    state:
        description:
            - State of the subnet group.
        default: present
        choices: ['present', 'absent']
        type: str
    identifier:
        description:
            - The name for the replication subnet group.
              This value is stored as a lowercase string.
              Must contain no more than 255 alphanumeric characters,
              periods, spaces, underscores, or hyphens. Must not be "default".
        type: str
        required: true
    description:
        description:
            - The description for the subnet group.
        type: str
        required: true
    subnet_ids:
        description:
            - A list containing the subnet ids for the replication subnet group,
              needs to be at least 2 items in the list.
        type: list
        elements: str
        required: true
author:
    - "Rui Moreira (@ruimoreira)"
extends_documentation_fragment:
    - amazon.aws.common.modules
    - amazon.aws.region.modules
    - amazon.aws.boto3
"""

EXAMPLES = r"""
- community.aws.dms_replication_subnet_group:
    state: present
    identifier: "dev-sngroup"
    description: "Development Subnet Group asdasdas"
    subnet_ids: ['subnet-id1', 'subnet-id2']
"""

RETURN = r""" # """

try:
    import botocore
except ImportError:
    pass  # caught by AnsibleAWSModule

from ansible_collections.amazon.aws.plugins.module_utils.retries import AWSRetry

from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule

backoff_params = dict(retries=5, delay=1, backoff=1.5)


@AWSRetry.jittered_backoff(**backoff_params)
def describe_subnet_group(connection, subnet_group):
    """checks if instance exists"""
    try:
        subnet_group_filter = dict(Name="replication-subnet-group-id", Values=[subnet_group])
        return connection.describe_replication_subnet_groups(Filters=[subnet_group_filter])
    except botocore.exceptions.ClientError:
        return {"ReplicationSubnetGroups": []}


@AWSRetry.jittered_backoff(**backoff_params)
def replication_subnet_group_create(connection, **params):
    """creates the replication subnet group"""
    return connection.create_replication_subnet_group(**params)


@AWSRetry.jittered_backoff(**backoff_params)
def replication_subnet_group_modify(connection, **modify_params):
    return connection.modify_replication_subnet_group(**modify_params)


@AWSRetry.jittered_backoff(**backoff_params)
def replication_subnet_group_delete(module, connection):
    subnetid = module.params.get("identifier")
    delete_parameters = dict(ReplicationSubnetGroupIdentifier=subnetid)
    return connection.delete_replication_subnet_group(**delete_parameters)


def replication_subnet_exists(subnet):
    """Returns boolean based on the existence of the endpoint
    :param endpoint: dict containing the described endpoint
    :return: bool
    """
    return bool(len(subnet["ReplicationSubnetGroups"]))


def create_module_params(module):
    """
    Reads the module parameters and returns a dict
    :return: dict
    """
    instance_parameters = dict(
        # ReplicationSubnetGroupIdentifier gets translated to lower case anyway by the API
        ReplicationSubnetGroupIdentifier=module.params.get("identifier").lower(),
        ReplicationSubnetGroupDescription=module.params.get("description"),
        SubnetIds=module.params.get("subnet_ids"),
    )

    return instance_parameters


def compare_params(module, param_described):
    """
    Compares the dict obtained from the describe function and
    what we are reading from the values in the template We can
    never compare passwords as boto3's method for describing
    a DMS endpoint does not return the value for
    the password for security reasons ( I assume )
    """
    modparams = create_module_params(module)
    changed = False
    # need to sanitize values that get returned from the API
    if "VpcId" in param_described.keys():
        param_described.pop("VpcId")
    if "SubnetGroupStatus" in param_described.keys():
        param_described.pop("SubnetGroupStatus")
    for paramname in modparams.keys():
        if paramname in param_described.keys() and param_described.get(paramname) == modparams[paramname]:
            pass
        elif paramname == "SubnetIds":
            subnets = []
            for subnet in param_described.get("Subnets"):
                subnets.append(subnet.get("SubnetIdentifier"))
            for modulesubnet in modparams["SubnetIds"]:
                if modulesubnet in subnets:
                    pass
        else:
            changed = True
    return changed


def create_replication_subnet_group(module, connection):
    try:
        params = create_module_params(module)
        return replication_subnet_group_create(connection, **params)
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
        module.fail_json_aws(e, msg="Failed to create DMS replication subnet group.")


def modify_replication_subnet_group(module, connection):
    try:
        modify_params = create_module_params(module)
        return replication_subnet_group_modify(connection, **modify_params)
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
        module.fail_json_aws(e, msg="Failed to Modify the DMS replication subnet group.")


def main():
    argument_spec = dict(
        state=dict(type="str", choices=["present", "absent"], default="present"),
        identifier=dict(type="str", required=True),
        description=dict(type="str", required=True),
        subnet_ids=dict(type="list", elements="str", required=True),
    )
    module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True)
    exit_message = None
    changed = False

    state = module.params.get("state")
    dmsclient = module.client("dms")
    subnet_group = describe_subnet_group(dmsclient, module.params.get("identifier"))
    if state == "present":
        if replication_subnet_exists(subnet_group):
            if compare_params(module, subnet_group["ReplicationSubnetGroups"][0]):
                if not module.check_mode:
                    exit_message = modify_replication_subnet_group(module, dmsclient)
                else:
                    exit_message = dmsclient
                changed = True
            else:
                exit_message = "No changes to Subnet group"
        else:
            if not module.check_mode:
                exit_message = create_replication_subnet_group(module, dmsclient)
                changed = True
            else:
                exit_message = "Check mode enabled"

    elif state == "absent":
        if replication_subnet_exists(subnet_group):
            if not module.check_mode:
                replication_subnet_group_delete(module, dmsclient)
                changed = True
                exit_message = "Replication subnet group Deleted"
            else:
                exit_message = dmsclient
                changed = True

        else:
            changed = False
            exit_message = "Replication subnet group does not exist"

    module.exit_json(changed=changed, msg=exit_message)


if __name__ == "__main__":
    main()
