# -*- coding: utf-8 -*-

import dnstwist

from certleak.util import listify
from .basicanalyzer import BasicAnalyzer


class DNStwistAnalyzer(BasicAnalyzer):
    """Analyzer for finding certificate updates for permutated domains (generated by dnstwist)"""
    name = "DNStwistAnalyzer"

    def __init__(self, actions, domainname, fuzzers=None, exceptions=None):
        """Analyzer for finding certificate updates for permutated domains (generated by dnstwist).
        Check https://github.com/elceef/dnstwist for more details!

        :param actions: A single action or a list of actions to be executed on every update
        :param domainname: The domainname of the target website
        :param fuzzers: A list of dnstwist fuzzers to use, e.g. "addition", "bitsquatting"
        :param exceptions: A list of domains to exclude from being matched
        """
        super().__init__(actions)
        self.domainname = domainname
        self.fuzzers = fuzzers
        self.exceptions = listify(exceptions)
        self.exceptions.append(domainname)

        # Generate pot. phishing domain names via dnstwist
        self.logger.info("Generating phishing domains via dnstwist for domain '{0}'".format(domainname))
        fuzz = dnstwist.DomainFuzz(domainname)
        fuzz.generate()
        res = fuzz.domains

        self.logger.info("Generated {0} permutated domains".format(len(res)))

        # dnstwist returns a list of dicts containing "fuzzer" and "domain-name" as elements
        # We need to generate a set of domain names out of it
        if fuzzers:
            # Skip certain fuzzers if the user wants to filter these out
            self.generated_domains = {domain.get("domain-name") for domain in res if domain.get("fuzzer") in self.fuzzers}
        else:
            self.generated_domains = {domain.get("domain-name") for domain in res}

        # Remove original domain and exceptions from set
        for exception_domain in self.exceptions:
            try:
                self.generated_domains.remove(exception_domain)
            except KeyError:
                self.logger.debug("Could not find domain {0} in dnstwist output!".format(exception_domain))

        self.logger.info("Using {0} permutated domains".format(len(self.generated_domains)))

    def match(self, update):
        """Check if any of the certificate domain names are contained in the list of generated pot. phishing domains

        :param update: An update object which should be matched
        :return: `bool` if the update has been matched
        """
        for domain in update.all_domains:
            if domain in self.generated_domains:
                # TODO implement "contained in" feature - e.g. for subdomains
                return True
        return False
