from parallels.core import messages
import logging

from parallels.core.actions.base.common_action import CommonAction
from parallels.core.actions.utils.logging_properties import LoggingProperties
from parallels.core.utils.restore_hosting_utils import get_restore_hosting_utils
from parallels.core.utils.imported_backups import ImportedBackups
from parallels.core.utils.common import unused

logger = logging.getLogger(__name__)


class ImportBackups(CommonAction):
	def get_description(self):
		return messages.IMPORT_BACKUP_DUMPS_TARGET_PANELS_REPOSITORY

	def get_failure_message(self, global_context):
		return messages.FAILED_IMPORT_BACKUP_DUMPS_TARGET_PANELS

	def get_logging_properties(self):
		"""Get how action should be logged to migration tools end-user

		:rtype: parallels.core.actions.utils.logging_properties.LoggingProperties
		"""
		return LoggingProperties(compound=False)

	def run(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		"""
		backups = set([])
		for subscription in global_context.iter_all_subscriptions():
			if not self._should_import_for_subscription(subscription):
				continue

			for backup in [subscription.full_converted_backup, subscription.full_converted_mail_backup]:
				if backup is not None:
					backups.add((backup, subscription.panel_target_server))

		for backup, panel_target_server in backups:
			self._import_backup(backup, panel_target_server)

	@staticmethod
	def _import_backup(backup, panel_target_server):
		# STEP #1: create utility objects
		target_backup_path = panel_target_server.get_session_file_path('plesk.backup')
		source_backup_path = backup.container.filename
		restore_hosting_utils = get_restore_hosting_utils(panel_target_server)

		# STEP #2: remove backup from target panel's repository if it already exists
		# If backup with such name already exists in target panel's repository
		# (for example, if migrator was interrupted before it cleans up backup file)
		# PMM will refuse to import it again
		# and we could get outdated backup, so remove backup file from target Plesk before import
		restore_hosting_utils.remove_backup(backup.backup_info_file)

		# STEP #3: upload backup
		logger.debug(messages.UPLOAD_BACKUP_DUMP_S_TARGET_NODE % source_backup_path)
		with panel_target_server.runner() as runner:
			runner.upload_file(source_backup_path, target_backup_path)

		# STEP #4: import backup to target panel's repository
		logger.debug(messages.IMPORT_BACKUP_DUMP_TARGET_PANELS_REPOSITORY)
		backup_prefix, backup_id = restore_hosting_utils.import_backup(target_backup_path)

		# STEP #5: index imported XML domain backup files
		# Index backup files after backup is imported: create dict with key -
		# domain name and value - backup XML file name.
		logger.debug(messages.CREATE_MAPPING_DOMAIN_NAME_BACKUP_XML)
		domain_to_backup_file = restore_hosting_utils.index_imported_domain_backup_files(backup_prefix, backup_id)
		logger.debug("Mapping of backup XML files: %r", domain_to_backup_file)

		# STEP #6: Put imported backup information to imported backup registry
		ImportedBackups.get_instance().add(backup, domain_to_backup_file)

	@staticmethod
	def _should_import_for_subscription(subscription):
		"""Whether we should import backup for that subscription

		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		:rtype: bool
		"""
		unused(subscription)
		return True
