import logging
import urllib2
import re
from xml.etree import ElementTree

from collections import defaultdict

from plesk_mail_migrator.utils.string_utils import is_empty
logger = logging.getLogger(__name__)

AUTOCONFIG_DB_URL = 'https://autoconfig.thunderbird.net/v1.1/'


def download_autoconfig_db(autoconfig_db_url=AUTOCONFIG_DB_URL):
    """Download autoconfig database of Mozilla/Thunderbird.

    Return database in simple format - dictionary:
    - keys - domain names of e-mail addresses
    - values - lists of hostnames of IMAP servers for corresponding e-mail domain
    For example: {
        ...
        'gmail.com': [
            'imap.gmail.com'
        ]
        ...
    }

    :rtype: dict[str | unicode, list[str | unicode]]
    """
    logger.info("Download index page")
    http_handler = urllib2.urlopen(autoconfig_db_url)
    contents = http_handler.read()

    logger.info("Find links to domain XML files")
    # Find links to per-domain XML files. Such links look like:
    # <a href="gmail.com">gmail.com</a>
    #
    # "/?=" symbols are excluded to exclude links to other sites, other directories,
    # and links with HTTP GET parameters - all these are not links to per-domain XML files
    domains = re.findall('<a href="([^"/?=]*)">', contents)
    logger.info("Found %s domain XML files", len(domains))

    imap_servers_map = defaultdict(list)

    for domain in domains:
        if domain in imap_servers_map:
            # There are multiple domains which have the same XML,
            # for example "https://autoconfig.thunderbird.net/v1.1/yandex.ru"
            # and "https://autoconfig.thunderbird.net/v1.1/ya.ru"
            # All domains for which XML is applicable are listed at "emailProvider/domain" XML node (see code below).
            # Download the XML only once.
            logger.info("Skip domain XML file for '%s' as the domain was already processed within another XML", domain)
            continue

        logger.info("Download domain XML file for '%s'", domain)

        domain_xml_http_handler = urllib2.urlopen('%s/%s' % (autoconfig_db_url, domain))
        domain_xml_contents = domain_xml_http_handler.read()
        tree = ElementTree.fromstring(domain_xml_contents)

        logger.info("Find information about IMAP servers in XML file for '%s'", domain)

        # collect all domains for which the XML is applicable
        all_domains_in_xml = {domain}
        for domain_node in tree.findall('emailProvider/domain'):
            all_domains_in_xml.add(domain_node.text)

        imap_server_hostname_templates = []

        for incoming_server_node in tree.findall('emailProvider/incomingServer'):
            if incoming_server_node.attrib.get('type') != 'imap':
                continue

            imap_server_hostname_template = incoming_server_node.findtext('hostname')

            if is_empty(imap_server_hostname_template):
                continue

            imap_server_hostname_templates.append(imap_server_hostname_template)

        for domain_in_xml in all_domains_in_xml:
            for imap_server_hostname_template in imap_server_hostname_templates:
                imap_server_hostname = imap_server_hostname_template.replace('%EMAILDOMAIN%', domain_in_xml)

                if '%' in imap_server_hostname:
                    # Skip all hostname templates which contain other variables than "%EMAILDOMAIN%":
                    # it is quite complex to handle them further, and actually there are no such
                    # IMAP server hostname templates in the database (for the July of 2018).
                    continue

                if imap_server_hostname not in imap_servers_map[domain_in_xml]:
                    imap_servers_map[domain_in_xml].append(imap_server_hostname)

    return imap_servers_map
