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 TransferErrorDocumentsBase(SubscriptionAction):
	def get_description(self):
		return "Transfer custom error documents"

	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 custom error documents types 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 custom error documents 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 custom error documents for site '%s' of subscription '%s' as is has no virtual hosting" % (
						site.name, subscription.name
					)
				)
				continue

			with global_context.safe.try_subscription(
				subscription.name,
				u"Transfer custom error documents of site '%s' and its virtual directories" % site.name,
				is_critical=False
			):
				self._transfer_site_error_documents(global_context, subscription, site)

	def _transfer_site_error_documents(self, global_context, subscription, site):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		vhost_error_documents = self._get_site_error_documents(global_context, subscription, site)
		vdirs_error_documents = self._get_site_vdir_error_documents(global_context, subscription, site)

		with subscription.web_target_server.runner() as runner_target:
			target_websrvmng_path = windows_path_join(
				subscription.web_target_server.plesk_dir,
				ur'admin\bin\websrvmng'
			)
			if vhost_error_documents is not None:
				logger.debug("Restore error documents of virtual host's root")
				runner_target.sh(
					'{websrvmng_path} --set-error-docs --vhost-name={vhost_name} --error-docs="{error_docs}"'.format(
						websrvmng_path=target_websrvmng_path, vhost_name=site.name.encode('idna'),
						error_docs=vhost_error_documents.replace('"', '\\"')
					))

			if vdirs_error_documents is not None:
				for vdir_name, vdir_error_documents in vdirs_error_documents.iteritems():
					logger.debug("Restore error documents of virtual directory '%s'", vdir_name)
					runner_target.sh(
						'{websrvmng_path} --set-error-docs --vhost-name={vhost_name} --vdir-name={vdir_name} --error-docs="{error_docs}"'.format(
							websrvmng_path=target_websrvmng_path,
							vhost_name=site.name.encode('idna'), vdir_name=vdir_name,
							error_docs=vdir_error_documents.replace('"', '\\"')
						))

	def _get_site_error_documents(self, global_context, subscription, site):
		"""
		Override in child classes

		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		return None

	def _get_site_vdir_error_documents(self, global_context, subscription, site):
		"""
		Override in child classes

		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		return None
