import logging
from parallels.core.checking import Problem

from parallels.plesk import messages
from parallels.plesk.utils.xml_rpc.plesk.operator.server import ServerOperator
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.utils.common import ilen

logger = logging.getLogger(__name__)


class CheckTargetLicenseLimits(CommonAction):
	def get_description(self):
		"""
		:rtype: basestring
		"""
		return messages.ACTION_CHECK_TARGET_LICENSE_LIMIT_DESCRIPTION

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:rtype: basestring
		"""
		return messages.ACTION_CHECK_TARGET_LICENSE_LIMIT_FAILURE

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

		If action is critical and it failed, migration tool completely stops.
		Otherwise it proceeds to the next steps of migrations.

		:rtype: bool
		"""
		return False

	def run(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:rtype: None
		"""
		plesk_api = global_context.conn.target.plesk_api()
		server_info = plesk_api.send(ServerOperator.Get([
			ServerOperator.Dataset.STAT, ServerOperator.Dataset.KEY
		])).data
		target_domains_count = int(server_info.statistics.objects.domains)
		target_domains_limit = int(server_info.key.properties.get('lim_dom', '-1'))
		logger.debug(messages.LOG_DOMAINS_ON_TARGET.format(domains_count=target_domains_count))
		logger.debug(messages.LOG_LICENSE_LIMIT_ON_TARGET.format(domains_count=target_domains_limit))

		if target_domains_limit < 0:
			# Negative means no limit, so this check is not necessary
			return

		existing_webspaces_by_name = {ws.name for ws in global_context.target_existing_objects.webspaces}
		migrated_domains_count = sum([
			1 + ilen(subscription.raw_dump.iter_addon_domains())  # subscription + addon domains
			for subscription in global_context.iter_all_subscriptions()
			if subscription.name not in existing_webspaces_by_name
		])
		logger.debug(messages.LOG_DOMAINS_ON_SOURCE.format(domains_count=migrated_domains_count))

		if target_domains_count + migrated_domains_count > target_domains_limit:
			global_context.pre_check_report.add_issue(
				Problem(
					'target_license_not_enough_domains',
					Problem.ERROR,
					messages.NOT_ENOUGH_DOMAINS_IN_LICENSE_ISSUE.format(
						available=target_domains_limit - target_domains_count,
						required=migrated_domains_count
					),
				),
				messages.NOT_ENOUGH_DOMAINS_IN_LICENSE_SOLUTION
			)
