from parallels.core.logging import get_logger
from parallels.core.utils.common import safe_string_repr
from parallels.hosting_check import DomainIssue
from parallels.hosting_check import Severity, DNSIssueType
from parallels.hosting_check.utils.dns_utils import DnsRequestTimeoutException
from parallels.hosting_check.utils.dns_utils import get_difference
from parallels.hosting_check.messages import MSG

logger = get_logger(__name__)


class DNSChecker:
    def __init__(
        self,
        max_difference_lines=3, save_external_report_data_function=None, 
        dns_server_name='PPA DNS server',
        difference_file_panel_id='ppa'
    ):
        self.max_difference_lines = max_difference_lines
        self.save_external_report_data_function = save_external_report_data_function
        self.dns_server_name = dns_server_name
        self.difference_file_panel_id = difference_file_panel_id

    def check(self, domains_to_check):
        issues = []

        def add_issue(severity, category, problem):
            issues.append(
                DomainIssue(
                    domain_name=domain_to_check.domain_name,
                    severity=severity,
                    category=category,
                    problem=problem
                )
            )

        for domain_to_check in domains_to_check:
            for dns_server_ip in domain_to_check.dns_servers:
                try:
                    difference = get_difference(
                        domain_to_check.dns_records, dns_server_ip
                    )

                    if len(difference) > 0:
                        if (
                            len(difference) <= self.max_difference_lines or
                            self.save_external_report_data_function is None
                        ): 
                            # put all differences to screen immediately
                            difference_str = MSG(
                                'dns_difference_full',
                                difference=u"\n".join(difference)
                            )
                        else:
                            # put first 3 differences to screen as an example,
                            # put all other differences into a separate file
                            filename = self.save_external_report_data_function(
                                "dns.%s.%s.difference.%s" % (
                                    self.difference_file_panel_id, 
                                    dns_server_ip, domain_to_check.domain_name
                                ), 
                                MSG(
                                    'dns_file_difference',
                                    server_ip=dns_server_ip,
                                    difference=u"\n".join(difference)
                                ) + "\n"
                            )
                            difference_str = MSG(
                                'dns_difference_example',
                                example_difference=u"\n".join(difference[:3]),
                                filename=filename
                            )

                        add_issue(
                            severity=Severity.ERROR, 
                            category=DNSIssueType.DIFFERENT_RECORDS,
                            problem=MSG(
                                DNSIssueType.DIFFERENT_RECORDS,
                                server_ip=dns_server_ip,
                                difference=difference_str
                            )
                        )
                except DnsRequestTimeoutException as e:
                    logger.debug(u"Exception:", exc_info=e)
                    # do not return any report comparing records - just a
                    # timeout message
                    add_issue(
                        severity=Severity.ERROR,
                        category=DNSIssueType.DNS_SERVER_TIMEOUT,
                        problem=MSG(
                            DNSIssueType.DNS_SERVER_TIMEOUT,
                            server_name=self.dns_server_name,
                            server_ip=e.server_ip
                        )
                    )
                except KeyboardInterrupt:
                    # for compatibility with python 2.4
                    raise
                except Exception as e:
                    logger.debug(u"Exception:", exc_info=e)
                    # do not return any report comparing records - just a
                    # general failure message
                    add_issue(
                        severity=Severity.WARNING,
                        category=DNSIssueType.INTERNAL_ERROR,
                        problem=MSG(
                            DNSIssueType.INTERNAL_ERROR,
                            reason=safe_string_repr(e),
                            server_name=self.dns_server_name, 
                            server_ip=dns_server_ip
                        )
                    )
        return issues
