import logging

from parallels.hosting_check.utils.dns_utils import \
	DnsRequestTimeoutException, get_difference_between_dns_servers 
from parallels.hosting_check import \
	DomainIssue, Severity, DNSForwardingIssueType
from parallels.hosting_check.messages import MSG

logger = logging.getLogger(__name__)

class DNSForwardingChecker(object):
	def __init__(
		self, max_difference_lines=3, 
		save_external_report_data_function=None
	):
		self.max_difference_lines = max_difference_lines
		self.save_external_report_data_function = \
			save_external_report_data_function

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

		for domain_to_check in domains_to_check:

			for source_dns_server_ip in domain_to_check.source_dns_servers:
				self._check_signle_source_dns_server(
					domain_to_check, source_dns_server_ip, 
					issues
				)

		return issues

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

		logger.debug(MSG(
			'dns_forwarding_log_checking',
			source_dns_server_ip=source_dns_server_ip,
			domain=domain_to_check.domain_name
		))

		try:
			difference = get_difference_between_dns_servers(
				domain_to_check.dns_records, 
				domain_to_check.target_dns_server, source_dns_server_ip
			)

			if len(difference) > 0:
				self._report_difference(
					domain_to_check, source_dns_server_ip, difference, issues
				)
		except DnsRequestTimeoutException, e:
			logger.debug(u"Exception:", exc_info=e)
			# do not show any report comparing records - just a timeout
			# message
			add_issue(
				severity=Severity.WARNING,
				category=DNSForwardingIssueType.DNS_SERVER_TIMEOUT,
				problem=MSG(
					DNSForwardingIssueType.DNS_SERVER_TIMEOUT,
					source_dns_server_ip=e.server_ip
				)
			)

		except Exception, e:
			logger.debug(u"Exception:", exc_info=e)
			# do not show any report comparing records - just a general
			# failure message
			add_issue(
				severity=Severity.WARNING,
				category=DNSForwardingIssueType.INTERNAL_ERROR,
				problem=MSG(
					DNSForwardingIssueType.INTERNAL_ERROR,
					reason=str(e),
					source_dns_server_ip=source_dns_server_ip
				)
			)

	def _report_difference(
		self, domain_to_check, source_dns_server_ip, difference, issues
	):
		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_forwarding_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.forwarding.difference.%s" % (domain_to_check.domain_name), 
				MSG(
					'dns_forwarding_difference_file',
					source_dns_server_ip=source_dns_server_ip,
					target_dns_server_ip=domain_to_check.target_dns_server,
					difference=u"\n".join(difference)
				)
			)
			difference_str = MSG(
				'dns_forwarding_difference_example',
				difference=u"\n".join(difference[:3]), 
				filename=filename
			)

		issues.append(
			DomainIssue(
				domain_name=domain_to_check.domain_name, 
				severity=Severity.WARNING,
				category=DNSForwardingIssueType.DIFFERENT_RECORDS,
				problem=MSG(
					DNSForwardingIssueType.DIFFERENT_RECORDS,
					source_dns_server_ip=source_dns_server_ip, 
					target_dns_server_ip=domain_to_check.target_dns_server, 
					difference=difference_str
				)
			)
		)
