import logging

from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.common.utils.plesk_utils import set_mime_types

logger = logging.getLogger(__name__)


class TransferMIMETypesBase(SubscriptionAction):
	def get_description(self):
		return "Transfer MIME types"

	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 MIME 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 MIME types 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
		"""
		logger.debug(u"Transfer MIME types for sites of subscription '%s'" % subscription.name)

		for site in subscription.converted_backup.iter_domains():
			if not site.is_virtual_hosting:
				logger.debug(
					u"Skip transfer MIME types for site '%s' of subscription '%s' as it has no virtual hosting" % (
						site.name, subscription.name
					)
				)
				continue

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

	def _transfer_site_mime_types(self, global_context, subscription, site):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type subscription: parallels.common.migrated_subscription.MigratedSubscription
		"""
		# Get MIME types from source panel
		vhost_mime_types = self._get_site_mime_types(global_context, subscription, site)
		vdirs_mime_types = self._get_site_vdir_mime_types(global_context, subscription, site)

		# Set MIME types on target panel
		if vhost_mime_types is not None:
			logger.debug("Restore MIME types of virtual host's root")
			set_mime_types(
				subscription.web_target_server, site.name,
				vhost_mime_types
			)

		if vdirs_mime_types is not None:
			for vdir_name, vdir_mime_types in vdirs_mime_types.iteritems():
				logger.debug("Restore MIME types of virtual directory '%s'", vdir_name)
				set_mime_types(
					subscription.web_target_server, site.name,
					vdir_mime_types, vdir_name
				)

	def _get_site_mime_types(self, global_context, subscription, site):
		"""Get MIME types of a site

		Override in child classes.

		Returns dictionary with keys - extensions, values - corresponding MIME types.
		If there are no MIME types for a site - returns None (default behavior)

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

	def _get_site_vdir_mime_types(self, global_context, subscription, site):
		"""Get MIME types of all virtual directories inside a site

		Override in child classes.

		Returns dictionary with:
		- key - virtual directory path (as it is presented on target server)
		- value - dictionary with:
			- key - extensions
			- values - corresponding MIME types
		If there are no virtual directories with MIME types - returns None (default behavior)

		The dictionary looks in the following way:
		{
			virtual directory name: {
				extension: mime type
			}
		}

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