from parallels.plesk.source.confixx import messages
import logging
import posixpath

import settings
from parallels.core.dump.data_model import DatabaseServer
from parallels.core.utils import plesk_utils
from parallels.plesk.source.confixx.pmm_agent import ConfixxPmmMigrationAgent
from parallels.plesk.source.confixx.server import ConfixxSourceServer
from parallels.plesk.source.confixx.utils import ConfixxConfiguration
from parallels.plesk.source.confixx.content.mail import ConfixxCopyMailContent
from parallels.plesk.utils.xml_rpc.plesk.operator.subscription import Ips
from parallels.plesk.source.plesk.infrastructure_checks import checks as infrastructure_checks
from parallels.core.utils.common import cached
import connections
import parallels.core.migrator
import parallels.plesk.source.confixx.utils
from parallels.plesk.source.legacy.migrator import PmmUnixMigrator
from parallels.plesk.source.confixx.global_context import ConfixxGlobalMigrationContext


class Migrator(PmmUnixMigrator):
	logger = logging.getLogger(__name__)

	def __init__(self, config):
		super(Migrator, self).__init__(config, settings)
		self.global_context.dump_agent = self._get_dump_agent()
		self.global_context.confixx_configuration = self._get_confixx_configuration()

	def _load_connections_configuration(self):
		return connections.MigratorConnections(self.global_context, self._get_target_panel())

	def _create_global_context(self):
		context = ConfixxGlobalMigrationContext()
		context.source_has_dns_forwarding = False
		return context

	# ======================== copy mail content ==============================

	def _copy_mail_content_single_subscription(self, migrator_server, subscription, issues):
		copy_mail = ConfixxCopyMailContent(
			self.global_context.confixx_configuration,
			agent_dir=self.global_context.dump_agent.agent_dir,
			mailmapping_tool='mailmapping.pl'
		)
		return copy_mail.copy_mail(self.global_context, migrator_server, subscription, issues)

	# ======================== databases =====================================

	def _get_src_db_server(self, db, backup):
		configuration = self.global_context.confixx_configuration
		return DatabaseServer(
			None,
			host='localhost',
			port='3306',
			login=configuration.get_mysql_user(),
			password=configuration.get_mysql_password(),
			dbtype='mysql',
			is_default=True,
		)

	def _get_mailserver_ip_by_subscription_name(
			self, source_settings, subscription_name
		):
		"""Confixx MySQL server IP equals to panel's IP; return None."""
		# TODO This seems to be wrong, why Confixx has no mail IP?
		return Ips(None, None)

	# ======================== infrastructure checks ==========================

	def _get_check_service_connection_commands(self):
		return {
			'web': self._check_unix_copy_web_content_rsync_connections,
			'mail': self._check_unix_copy_mail_content_rsync_connections,
			'db': self._check_unix_copy_db_content_scp_connections
		}

	def _check_infrastructure_connections(self, report, safe):
		self.logger.info(messages.LOG_CHECK_CONNECTION_REQUIREMENTS)

		for service in ('web', 'mail', 'db'):
			self._check_connection(service, report, safe)

	def _check_connection(self, service, report, safe):
		service_checkers = self._get_check_service_connection_commands()
		report_messages = {
			'title':
				messages.REPORT_TITLE_INFRASTRUCTURE_CHECKS_CONNECTIONS,
			'error':
				messages.FAILED_TO_CHECK_CONNECTIONS}
		report = report.subtarget(report_messages['title'] % service, None)
		checks = infrastructure_checks.InfrastructureChecks()
		with safe(report, report_messages['error'] % service):
			service_checkers[service](checks, report)

	def _check_disk_space(self, report, safe):
		self.logger.info(messages.LOG_CHECK_DISK_SPACE_REQUIREMENTS)
		disk_space_report = report.subtarget(messages.REPORT_TARGET_DISK_SPACE_REQUIREMENTS, None)
		super(Migrator, self)._check_disk_space_unix(disk_space_report)

	# ======================== utility functions ==============================

	@cached
	def _get_confixx_configuration(self):
		return ConfixxConfiguration(
			self.conn.confixx, 
			self._get_dump_agent().get_confixx_config_path()
		)

	@cached # to avoid re-deploying, have a single PMM agent object
	def _get_dump_agent(self):
		migrator_dump_dir = posixpath.join(
			plesk_utils.get_migrator_root_path(parallels.plesk.source.confixx),
			'extras', 'pmm')
		return ConfixxPmmMigrationAgent(
			self.global_context,
			self.conn.confixx,
			migrator_dump_dir,
			self._get_settings()
		)

	@cached
	def _get_source_node(self, node_id):
		node_settings = self._get_source_servers()[node_id]
		return ConfixxSourceServer(
			node_id, node_settings, self.global_context.confixx_configuration
		)