import logging

from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.common.utils.windows_utils import path_join as windows_path_join

logger = logging.getLogger(__name__)


class TransferVirtualDirectoriesBase(SubscriptionAction):
	def get_description(self):
		return "Transfer virtual directories"

	def is_critical(self):
		"""If action is critical or not

		If action is critical and it failed for a subscription, migration tool
		won't run the next operations for the subscription.

		:rtype: bool
		"""
		return False

	def filter_subscription(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		if not subscription.is_windows:
			return False
		if not subscription.converted_backup.is_virtual_hosting:
			logger.debug(
				u"Skip transfer virtual directories for subscription '%s' as is has no virtual hosting" % subscription.name)
			return False

		return True

	def get_failure_message(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		return "Failed to transfer virtual directories for subscription '%s'" % subscription.name

	def run(self, global_context, subscription):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		for site in subscription.converted_backup.iter_domains():
			if not site.is_virtual_hosting:
				logger.debug(
					u"Skip transfer virtual directories for site '%s' of subscription '%s' "
					u"as is has no virtual hosting" % (
						site.name, subscription.name)
					)
				continue

			with global_context.safe.try_subscription(
					subscription.name,
					u"Transfer virtual directories of site '%s'" % site.name,
					is_critical=False
			):
				self._transfer_site_vdirs(global_context, subscription, site)

	def _transfer_site_vdirs(self, global_context, subscription, site):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		# Fetch information about virtual directories
		vdir_info = self._get_site_vdirs_xml(global_context, subscription, site)

		if vdir_info is None:
			logger.debug(
				u"No virtual directories information for site '%s', won't transfer them" % site.name
			)
			return

		# Restore virtual directories
		self._restore_vdir_xml(subscription, site, vdir_info)

	def _restore_vdir_xml(self, subscription, site, vdir_info):
		"""
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		server = subscription.web_target_server
		with server.runner() as runner:
			target_websrvmng_path = windows_path_join(server.plesk_dir, ur'admin\bin\websrvmng')

			vdir_info_filename = server.get_session_file_path('vdirs.xml')
			runner.upload_file_content(vdir_info_filename, vdir_info)
			runner.sh(
				'{websrvmng_path} --update-vdirs --vhost-name={vhost_name} --vdir-config={vdir_config_file}',
				dict(
					websrvmng_path=target_websrvmng_path, vhost_name=site.name.encode('idna'),
					vdir_config_file=vdir_info_filename
				)
			)

	def _get_site_vdirs_xml(self, global_context, subscription, site):
		"""Get virtual directories XML for specified site

		Override in child classes.

		Returned virtual directories XML should contain all
		paths according to the target server, not source server.
		Returns XML as string.
		"""
		return None
