#!/usr/bin/python
#
# Copyright (c) 2019 Zim Kalinowski, (@zikalino)
#
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
__metaclass__ = type


DOCUMENTATION = '''
---
module: azure_rm_cosmosdbaccount_info
version_added: "0.1.2"
short_description: Get Azure Cosmos DB Account facts
description:
    - Get facts of Azure Cosmos DB Account.

options:
    resource_group:
        description:
            - Name of an Azure resource group.
        type: str
    name:
        description:
            - Cosmos DB database account name.
        type: str
    tags:
        description:
            - Limit results by providing a list of tags. Format tags as 'key' or 'key:value'.
        type: list
        elements: str
    retrieve_keys:
        description:
            - Retrieve keys and connection strings.
        type: str
        choices:
            - all
            - readonly
    retrieve_connection_strings:
        description:
            - Retrieve connection strings.
        type: bool

extends_documentation_fragment:
    - azure.azcollection.azure

author:
    - Zim Kalinowski (@zikalino)

'''

EXAMPLES = '''
- name: Get instance of Database Account
  azure_rm_cosmosdbaccount_info:
    resource_group: myResourceGroup
    name: testaccount

- name: List instances of Database Account
  azure_rm_cosmosdbaccount_info:
    resource_group: myResourceGroup
    tags:
      - key
      - key:value
'''

RETURN = '''
accounts:
    description: A list of dictionaries containing facts for Database Account.
    returned: always
    type: complex
    contains:
        id:
            description:
                - The unique resource identifier of the database account.
            returned: always
            type: str
            sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.DocumentDB/databaseAccount
                     s/testaccount"
        resource_group:
            description:
                - Name of an Azure resource group.
            returned: always
            type: str
            sample: myResourceGroup
        name:
            description:
                - The name of the database account.
            returned: always
            type: str
            sample: testaccount
        location:
            description:
                - The location of the resource group to which the resource belongs.
            returned: always
            type: str
            sample: westus
        kind:
            description:
                - Indicates the type of database account.
            returned: always
            type: str
            sample: global_document_db
        consistency_policy:
            description:
                - Consistency policy.
            returned: always
            type: complex
            contains:
                default_consistency_level:
                    description:
                        - Default consistency level.
                    returned: always
                    type: str
                    sample: session
                max_interval_in_seconds:
                    description:
                        - Maximum interval in seconds.
                    returned: always
                    type: int
                    sample: 5
                max_staleness_prefix:
                    description:
                        - Maximum staleness prefix.
                    returned: always
                    type: int
                    sample: 100
        failover_policies:
            description:
                - The list of new failover policies for the failover priority change.
            returned: always
            type: complex
            contains:
                name:
                    description:
                        - Location name.
                    returned: always
                    type: str
                    sample: eastus
                failover_priority:
                    description:
                        - Failover priority.
                    returned: always
                    type: int
                    sample: 0
                id:
                    description:
                        - Read location ID.
                    returned: always
                    type: str
                    sample: testaccount-eastus
        read_locations:
            description:
                - Read locations.
            returned: always
            type: complex
            contains:
                name:
                    description:
                        - Location name.
                    returned: always
                    type: str
                    sample: eastus
                failover_priority:
                    description:
                        - Failover priority.
                    returned: always
                    type: int
                    sample: 0
                id:
                    description:
                        - Read location ID.
                    returned: always
                    type: str
                    sample: testaccount-eastus
                document_endpoint:
                    description:
                        - Document endpoint.
                    returned: always
                    type: str
                    sample: https://testaccount-eastus.documents.azure.com:443/
                provisioning_state:
                    description:
                        - Provisioning state.
                    returned: always
                    type: str
                    sample: Succeeded
        write_locations:
            description:
                - Write locations.
            returned: always
            type: complex
            contains:
                name:
                    description:
                        - Location name.
                    returned: always
                    type: str
                    sample: eastus
                failover_priority:
                    description:
                        - Failover priority.
                    returned: always
                    type: int
                    sample: 0
                id:
                    description:
                        - Read location ID.
                    returned: always
                    type: str
                    sample: testaccount-eastus
                document_endpoint:
                    description:
                        - Document endpoint.
                    returned: always
                    type: str
                    sample: https://testaccount-eastus.documents.azure.com:443/
                provisioning_state:
                    description:
                        - Provisioning state.
                    returned: always
                    type: str
                    sample: Succeeded
        database_account_offer_type:
            description:
                - Offer type.
            returned: always
            type: str
            sample: Standard
        enable_free_tier:
            description:
                - If enabled the account is free-tier.
            returned: always
            type: bool
            sample: true
            version_added: "1.10.0"
        ip_range_filter:
            description:
                - (deprecated) Enabled IP range filter.
                - This value has been deprecated, and will be removed in a later version. Use c(ip_rules) instead.
            returned: always
            type: str
            sample: 10.10.10.10
        ip_rules:
            description:
                - The IP addresses or IP address ranges in CIDR form included as the allowed list of client IPs.
            returned: always
            type: list
            sample: ["10.10.10.10", "20.20.20.20/28"]
            version_added: "1.10.0"
        is_virtual_network_filter_enabled:
            description:
                - Enable virtual network filter.
            returned: always
            type: bool
            sample: true
        enable_automatic_failover:
            description:
                - Enable automatic failover.
            returned: always
            type: bool
            sample: true
        enable_cassandra:
            description:
                - Enable Cassandra.
            returned: always
            type: bool
            sample: true
        enable_table:
            description:
                - Enable Table.
            returned: always
            type: bool
            sample: true
        enable_gremlin:
            description:
                - Enable Gremlin.
            returned: always
            type: bool
            sample: true
        mongo_version:
            description:
                - Server version for the MongoDB account.
                - Only used for c(kind) = i(mongo_db); otherwise value is null/none.
            returned: always
            type: str
            sample: "4.0"
            version_added: "1.10.0"
        public_network_access:
            description:
                - If public network access is allowed to the server.
            returned: always
            type: str
            sample: Enabled
            version_added: "1.10.0"
        virtual_network_rules:
            description:
                - List of Virtual Network ACL rules configured for the Cosmos DB account.
            type: list
            contains:
                subnet:
                    description:
                        - Resource id of a subnet.
                    type: str
                    sample: "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/virtualNet
                             works/testvnet/subnets/testsubnet1"
                ignore_missing_v_net_service_endpoint:
                    description:
                        - Create Cosmos DB account without existing virtual network service endpoint.
                    type: bool
        enable_multiple_write_locations:
            description:
                - Enable multiple write locations.
            returned: always
            type: bool
            sample: true
        document_endpoint:
            description:
                - Document endpoint.
            returned: always
            type: str
            sample: https://testaccount.documents.azure.com:443/
        provisioning_state:
            description:
                - Provisioning state of Cosmos DB.
            returned: always
            type: str
            sample: Succeeded
        primary_master_key:
            description:
                - Primary master key.
            returned: when requested
            type: str
            sample: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        secondary_master_key:
            description:
                - Primary master key.
            returned: when requested
            type: str
            sample: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        primary_readonly_master_key:
            description:
                - Primary master key.
            returned: when requested
            type: str
            sample: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        secondary_readonly_master_key:
            description:
                - Primary master key.
            returned: when requested
            type: str
            sample: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        connection_strings:
            description:
                - List of connection strings.
            type: list
            returned: when requested
            contains:
                connection_string:
                    description:
                        - Description of connection string.
                    type: str
                    returned: always
                    sample: Primary SQL Connection String
                description:
                    description:
                        - Connection string.
                    type: str
                    returned: always
                    sample: "AccountEndpoint=https://testaccount.documents.azure.com:443/;AccountKey=xxxxx"
        tags:
            description:
                - Tags assigned to the resource. Dictionary of "string":"string" pairs.
            returned: always
            type: dict
            sample: { "tag1":"abc" }
'''

from ansible_collections.azure.azcollection.plugins.module_utils.azure_rm_common import AzureRMModuleBase
from ansible.module_utils.common.dict_transformations import _camel_to_snake

try:
    from azure.core.exceptions import ResourceNotFoundError
    from azure.mgmt.cosmosdb import CosmosDBManagementClient
except ImportError:
    # This is handled in azure_rm_common
    pass


class AzureRMCosmosDBAccountInfo(AzureRMModuleBase):
    def __init__(self):
        # define user inputs into argument
        self.module_arg_spec = dict(
            resource_group=dict(
                type='str'
            ),
            name=dict(
                type='str'
            ),
            tags=dict(
                type='list',
                elements='str'
            ),
            retrieve_keys=dict(
                type='str',
                choices=['all', 'readonly']
            ),
            retrieve_connection_strings=dict(
                type='bool'
            )
        )
        # store the results of the module operation
        self.results = dict(
            changed=False
        )
        self.mgmt_client = None
        self.resource_group = None
        self.name = None
        self.tags = None
        self.retrieve_keys = None
        self.retrieve_connection_strings = None

        super(AzureRMCosmosDBAccountInfo, self).__init__(self.module_arg_spec, supports_check_mode=True, supports_tags=False, facts_module=True)

    def exec_module(self, **kwargs):

        is_old_facts = self.module._name == 'azure_rm_cosmosdbaccount_facts'
        if is_old_facts:
            self.module.deprecate("The 'azure_rm_cosmosdbaccount_facts' module has been renamed to 'azure_rm_cosmosdbaccount_info'", version=(2.9, ))

        for key in self.module_arg_spec:
            setattr(self, key, kwargs[key])
        self.mgmt_client = self.get_mgmt_svc_client(CosmosDBManagementClient,
                                                    base_url=self._cloud_environment.endpoints.resource_manager)

        if self.name is not None:
            self.results['accounts'] = self.get()
        elif self.resource_group is not None:
            self.results['accounts'] = self.list_by_resource_group()
        else:
            self.results['accounts'] = self.list_all()
        return self.results

    def get(self):
        response = None
        results = []
        try:
            response = self.mgmt_client.database_accounts.get(resource_group_name=self.resource_group,
                                                              account_name=self.name)
            self.log("Response : {0}".format(response))
        except ResourceNotFoundError as e:
            self.log('Could not get facts for Database Account.')

        if response and self.has_tags(response.tags, self.tags):
            results.append(self.format_response(response))

        return results

    def list_by_resource_group(self):
        response = None
        results = []
        try:
            response = self.mgmt_client.database_accounts.list_by_resource_group(resource_group_name=self.resource_group)
            self.log("Response : {0}".format(response))
        except Exception as e:
            self.log('Could not get facts for Database Account.')

        if response is not None:
            for item in response:
                if self.has_tags(item.tags, self.tags):
                    results.append(self.format_response(item))

        return results

    def list_all(self):
        response = None
        results = []
        try:
            response = self.mgmt_client.database_accounts.list()
            self.log("Response : {0}".format(response))
        except Exception as e:
            self.log('Could not get facts for Database Account.')

        if response is not None:
            for item in response:
                if self.has_tags(item.tags, self.tags):
                    results.append(self.format_response(item))

        return results

    def format_response(self, item):
        d = item.as_dict()
        d = {
            'id': d.get('id'),
            'resource_group': self.parse_resource_to_dict(d.get('id')).get('resource_group'),
            'name': d.get('name', None),
            'location': d.get('location', '').replace(' ', '').lower(),
            'kind': _camel_to_snake(d.get('kind', None)),
            'consistency_policy': {'default_consistency_level': _camel_to_snake(d['consistency_policy']['default_consistency_level']),
                                   'max_interval_in_seconds': d['consistency_policy']['max_interval_in_seconds'],
                                   'max_staleness_prefix': d['consistency_policy']['max_staleness_prefix']},
            'failover_policies': [{'name': fp['location_name'].replace(' ', '').lower(),
                                   'failover_priority': fp['failover_priority'],
                                   'id': fp['id']} for fp in d['failover_policies']],
            'read_locations': [{'name': rl['location_name'].replace(' ', '').lower(),
                                'failover_priority': rl['failover_priority'],
                                'id': rl['id'],
                                'document_endpoint': rl['document_endpoint'],
                                'provisioning_state': rl['provisioning_state']} for rl in d['read_locations']],
            'write_locations': [{'name': wl['location_name'].replace(' ', '').lower(),
                                 'failover_priority': wl['failover_priority'],
                                 'id': wl['id'],
                                 'document_endpoint': wl['document_endpoint'],
                                 'provisioning_state': wl['provisioning_state']} for wl in d['write_locations']],
            'database_account_offer_type': d.get('database_account_offer_type'),
            'enable_free_tier': d.get('enable_free_tier'),
            'ip_rules': [ip['ip_address_or_range'] for ip in d.get('ip_rules', [])],
            'ip_range_filter': ",".join([ip['ip_address_or_range'] for ip in d.get('ip_rules', [])]),
            'is_virtual_network_filter_enabled': d.get('is_virtual_network_filter_enabled'),
            'enable_automatic_failover': d.get('enable_automatic_failover'),
            'enable_cassandra': 'EnableCassandra' in d.get('capabilities', []),
            'enable_table': 'EnableTable' in d.get('capabilities', []),
            'enable_gremlin': 'EnableGremlin' in d.get('capabilities', []),
            'mongo_version': d.get('api_properties', {}).get('server_version'),
            'public_network_access': d.get('public_network_access'),
            'virtual_network_rules': d.get('virtual_network_rules'),
            'enable_multiple_write_locations': d.get('enable_multiple_write_locations'),
            'document_endpoint': d.get('document_endpoint'),
            'provisioning_state': d.get('provisioning_state'),
            'tags': d.get('tags', None)
        }

        if self.retrieve_keys == 'all':
            keys = self.mgmt_client.database_accounts.list_keys(resource_group_name=self.resource_group,
                                                                account_name=self.name)
            d['primary_master_key'] = keys.primary_master_key
            d['secondary_master_key'] = keys.secondary_master_key
            d['primary_readonly_master_key'] = keys.primary_readonly_master_key
            d['secondary_readonly_master_key'] = keys.secondary_readonly_master_key
        elif self.retrieve_keys == 'readonly':
            keys = self.mgmt_client.database_accounts.get_read_only_keys(resource_group_name=self.resource_group,
                                                                         account_name=self.name)
            d['primary_readonly_master_key'] = keys.primary_readonly_master_key
            d['secondary_readonly_master_key'] = keys.secondary_readonly_master_key
        if self.retrieve_connection_strings:
            connection_strings = self.mgmt_client.database_accounts.list_connection_strings(resource_group_name=self.resource_group,
                                                                                            account_name=self.name)
            d['connection_strings'] = connection_strings.as_dict()
        return d


def main():
    AzureRMCosmosDBAccountInfo()


if __name__ == '__main__':
    main()
