import logging
from contextlib import closing

from parallels.plesk.source.custom import messages
import connections
from parallels.core.migrator import Migrator as CommonMigrator
from parallels.plesk.source.custom.hosting_description.converter_to_dump import HostingDescriptionToPleskDumpConverter
from parallels.plesk.source.custom.migrated_subscription import CustomPanelMigratedSubscription
from parallels.plesk.source.custom.session_files import CustomPanelSessionFiles
from parallels.plesk.source.custom.global_context import CustomPanelGlobalMigrationContext


logger = logging.getLogger(__name__)


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

	def __init__(self, config):
		super(Migrator, self).__init__(config)

	def iter_shallow_dumps(self):
		return self.iter_all_server_raw_dumps()

	def iter_all_server_raw_dumps(self):
		for source_info in self.global_context.get_sources_info():
			yield source_info.id, source_info.load_raw_dump()

	def iter_panel_server_raw_dumps(self):
		return self.iter_all_server_raw_dumps()

	def iter_converted_dumps(self):
		for source_info in self.global_context.get_sources_info():
			with closing(self.load_converted_dump(source_info.id)) as dump:
				yield source_info.id, dump

	def iter_converted_backups(self):
		return self.iter_converted_dumps()

	def create_plesk_config_dump_from_hosting_description(self):
		converter = HostingDescriptionToPleskDumpConverter()
		converter.write_dump(
			hosting_description_config=connections.HostingDescriptionConfig(
				source_id='hosting-description',
				path=self.global_context.options.source_file,
				file_format=self.global_context.options.source_format
			),
			target_dump_filename=self.global_context.options.target_file,
			database_servers=list(self.global_context.conn.iter_database_servers())
		)

	def _subscription_is_windows(self, subscription_name, plesk_id=None):
		if plesk_id is not None:
			return self.get_panel_server_raw_dump(plesk_id).is_windows
		for _, raw_dump in self.iter_all_server_raw_dumps():
			if raw_dump.has_subscription(subscription_name):
				return raw_dump.is_windows
		raise Exception(messages.UNABLE_TO_GET_DUMP_WITH_SPECIFIED_SUBSCRIPTION)

	def _get_source_servers(self):
		return {}

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

	def _create_global_context(self):
		return CustomPanelGlobalMigrationContext()

	def _create_session_files(self):
		return CustomPanelSessionFiles(self.conn, self._get_migrator_server())

	def _get_source_web_node(self, subscription_name):
		return self._get_source_subscription_node(subscription_name)

	def _get_source_mail_node(self, subscription_name):
		return self._get_source_subscription_node(subscription_name)

	def _get_source_subscription_node(self, subscription_name):
		subscription = self._create_migrated_subscription(subscription_name)
		source_node_id = subscription.model.source
		return self.global_context.conn.get_source_server_by_id(source_node_id)

	def _get_source_db_node(self, source_id):
		return self.global_context.conn.get_source_server_by_id(source_id)

	def _create_migrated_subscription(self, name):
		return CustomPanelMigratedSubscription(self, name)

	def _get_rsync(self, source_server, target_server, source_ip=None):
		return self.global_context.rsync_pool.get(
			source_server, target_server,
			# specify "/cygdrive" as virtual hosts root, to be able to copy files
			# specified by absolute paths in hosting description file
			'/cygdrive'
		)

	def _get_subscription_content_ip(self, sub):
		return self.global_context.conn.get_source_server_by_id(sub.source).ip
