from parallels.core import messages
import logging
from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.plesk.utils.xml_rpc.plesk import operator as plesk_ops

logger = logging.getLogger(__name__)


class RestoreCatchAllSmartermailAssimilate(SubscriptionAction):
	"""This is a HACK: when webspace is created we do not pass disable provisioning flag,
	even if working in SmarterMail assimilate mode.
	Actually it is quite difficult to pass it when creating webspace.
	So, provisioning happens, and SmarterMail APS resets catch-all configuration.
	"""

	def get_description(self):
		return messages.RESTORE_CATCHALL_SETTINGS_FOR_SMARTERMAIL_ASSIMILATION

	def get_failure_message(self, global_context, subscription):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		"""
		return (
			messages.FAILED_RESTORE_CATCHALL_SETTINGS_FOR_SMARTERMAIL % subscription.name
		)

	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.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		"""
		has_mail = subscription.converted_dump.mailsystem is not None
		return has_mail and subscription.is_mail_assimilate

	def run(self, global_context, subscription):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		"""
		catch_all_value = subscription.converted_dump.mailsystem.get_catch_all()
		if catch_all_value is not None and '@' in catch_all_value:
			subscription_info = global_context.conn.target.plesk_api().send(
				plesk_ops.SubscriptionOperator.Get(
					filter=plesk_ops.SubscriptionOperator.FilterByName([subscription.name]),
					dataset=[plesk_ops.SubscriptionOperator.Dataset.GEN_INFO]
				)
			)
			if len(subscription_info) != 1:
				raise Exception(messages.EXPECTED_EXACTLY_ONE_SUBSCRIPTION_GOT_S, len(subscription_info))
			subscription_id, _ = subscription_info[0].data

			for nonexistent_user in [
				# first disable catch-all, so when enabling catch-all APSMail
				# won't decide that there is nothing to change
				plesk_ops.MailOperator.SetPrefs.NonexistentUserReject(),
				plesk_ops.MailOperator.SetPrefs.NonexistentUserForward(catch_all_value),
			]:
				results = global_context.conn.target.plesk_api().send(plesk_ops.MailOperator.SetPrefs(
					filter=plesk_ops.MailOperator.FilterBySiteId([subscription_id]),
					nonexistent_user=nonexistent_user
				))
				for result in results:
					result.check()
