import logging

from parallels.common.hosting_check.entity_source.common import \
	HostingObjectSubscriptionBase
from parallels.common.hosting_check import \
	BaseHostingObject, ChildHostingObjectsList, HostingCheckEntitiesList
from parallels.common.utils import plesk_api_utils

from parallels.hosting_check import DomainMailService
from parallels.hosting_check import User

logger = logging.getLogger(__name__)

class HostingObjectMailSubscription(HostingObjectSubscriptionBase):
	"""Source for hosting checks - subscription with mail hosting
	
	Arguments:
	- backup - source backup instance
	  (parallels.common.plesk_backup.plesk_backup_xml.PleskBackupSource*
	- subscription - subscription from backup
	  (parallels.common.plesk_backup.model.Subscription*)
	- create_migrated_subscription - function that can create instances of
	  common.migrated_subscription.MigrationSubscription
	- use_target_server_info - is fetch target server to add target_panel_mail_users to result (bool)
	"""
	def __init__(
		self, backup, subscription, create_migrated_subscription, use_target_server_info
	):
		super(HostingObjectMailSubscription, self).__init__(
			backup, subscription
		)
		self.create_migrated_subscription = create_migrated_subscription
		self.use_target_server_info = use_target_server_info

	def get_child_hosting_objects(self):
		"""Get child hosting objects (mail domains) to check 
		
		Return: ChildHostingObjectsList which contains list of
		objects-subclasses of BaseHostingObject class
		"""
		result = ChildHostingObjectsList()

		subscription = self.create_migrated_subscription(
			self.subscription.name
		)

		if subscription.converted_mail_backup is None:
			logger.debug(
				"Subscription '%s' is not presented on mail server, "
				"do not check mail for it",
				subscription.name
			)
			return result

		if not subscription.converted_mail_backup.is_enabled:
			logger.debug(
				u"Skipped checking mailboxes of the subscription "
				u"%s because it is suspended" % (subscription.name)
			)
			return result
		if (
			subscription.converted_mail_backup.mailsystem is None 
			or 
			not subscription.converted_mail_backup.mailsystem.enabled
		):
			logger.debug(
				u"Skipped checking mailboxes of the subscription "
				u"%s because it has no mail service" % (subscription.name)
			)
			return result

		for domain in subscription.converted_mail_backup.iter_domains():
			result.child_hosting_objects.append(
				HostingObjectMailDomain(subscription, domain.name, self.use_target_server_info)
			)

		return result

class HostingObjectMailDomain(BaseHostingObject):
	"""Source for hosting checks - domain with mail hosting
	
	Domain may be represented by main domain of subscription or
	addon domain 

	Arguments:
	- subscription - instance of MigrationSubscription
	- domain_name - name of domain to be checked (string)
	- use_target_server_info - is fetch target server to add target_panel_mail_users to result
	"""
	def __init__(self, subscription, domain_name, use_target_server_info):
		self.subscription = subscription
		self.domain_name = domain_name
		self.name = domain_name
		self.type = 'Mail domain'
		self.use_target_server_info = use_target_server_info

	def get_hosting_check_entities(self):
		"""Return mail service to be checked.

		Returns: an object of type 'HostingCheckEntitiesList'
		"""
		raw_domain = self.subscription.raw_mail_backup.get_domain(
			self.domain_name
		)
		converted_domain = self.subscription.converted_mail_backup.get_domain(
			self.domain_name
		)

		result = HostingCheckEntitiesList()

		if not converted_domain.is_enabled:
			logger.debug(
				u"Skipped checking mail service of the domain %s "
				u"because it is suspended" % (self.domain_name)
			)
			return result

		def get_backup_users(backup_domain):
			return [
				User(mailbox.full_name, mailbox.password)
				for mailbox in backup_domain.iter_mailboxes()
				if (
					mailbox.enabled 
					and 
					mailbox.password is not None 
					and 
					mailbox.password != '' 
					and 
					mailbox.password_type == 'plain'
				)
			]

		source_users = get_backup_users(raw_domain)
		target_users = get_backup_users(converted_domain)

		target_panel_mail_users = None
		if self.use_target_server_info:
			target_panel_mail_users = plesk_api_utils.list_mail_users(
				self.subscription.panel_target_server.plesk_api(),
				self.domain_name
			)

		domain_to_check = DomainMailService(
			domain_name=self.domain_name,
			source_mail_server_ip=self.subscription.source_mail_ip,
			mail_server_ip=self.subscription.target_mail_ip,
			users=target_users,
			source_users=source_users,
			target_panel_mail_users=target_panel_mail_users
		)

		result.hosting_check_entities.append(domain_to_check)
		return result
