from parallels.core import messages
import logging

import parallels.hosting_check
from parallels.core import checking
from parallels.core.hosting_check.entity_source.common import \
	HostingObjectSubscriptionBase
from parallels.core.hosting_check import \
	BaseHostingObject, ChildHostingObjectsList, HostingCheckEntitiesList
from parallels.core.hosting_check.utils.runner_adapter import \
	HostingCheckerRunnerAdapter

logger = logging.getLogger(__name__)


class HostingObjectWebSubscription(HostingObjectSubscriptionBase):
	"""Source for hosting checks - subscription with web hosting"""
	def __init__(self, backup, subscription, create_migrated_subscription):
		"""
		Arguments:
		- backup - source backup instance
		  (parallels.core.dump.dump.PleskBackupSource*
		- subscription - subscription from backup 
		  (parallels.core.dump.model.Subscription*)
		- create_migrated_subscription - function that can create instances of
		  common.migrated_subscription.MigrationSubscription
		"""
		super(HostingObjectWebSubscription, self).__init__(
			backup, subscription
		)
		self.create_migrated_subscription = create_migrated_subscription 

	def get_child_hosting_objects(self):
		"""Get child hosting objects (web domains) to check 
		
		Return: ChildHostingObjectsList which contains list of
		objects-subclasses of BaseHostingObject class
		"""
		subscription = self.create_migrated_subscription(
			self.subscription.name
		)

		result = ChildHostingObjectsList()
		if not subscription.converted_dump.is_enabled:
			logger.debug(
				messages.SKIPPED_CHECKING_SITES_SUBSCRIPTION_S_BECAUSE % 
				self.subscription.name
			)
			return result

		for domain in subscription.converted_dump.iter_domains():
			if subscription.is_fake and domain.name == subscription.name:
				continue
			result.child_hosting_objects.append(
				HostingObjectWebDomain(
					subscription, domain.name
				)
			)
		return result

class HostingObjectWebDomain(BaseHostingObject):
	"""Source for hosting checks - domain with web hosting
	
	Domain may be represented by main domain of subscription,
	addon domain or subdomain
	"""
	def __init__(self, subscription, domain_name):
		"""
		Arguments:
		- subscription - instance of MigrationSubscription
		- domain_name - name of domain to be checked (string)
		"""
		self.subscription = subscription
		self.name = domain_name

		if subscription.is_windows:
			self.type = u"IIS web site"
		else:
			self.type = u"Apache web site"

	def get_hosting_check_entities(self):
		result = HostingCheckEntitiesList()

		converted_domain = self.subscription.converted_dump.get_domain(
			self.name
		)
		raw_domain = self.subscription.raw_dump.get_domain(
			self.name
		)
		raw_subscription = self.subscription.raw_dump

		# if there is no site, do not check it
		if converted_domain.hosting_type == 'none':
			logger.debug(
				messages.SKIPPED_CHECKING_SITES_DOMAIN_S_BECAUSE % self.name
			)
			return result

		if not converted_domain.is_enabled:
			logger.debug(
				messages.SKIPPED_CHECKING_SITE_S_SUBSCRIPTION_S % (
					self.name, self.subscription.name
				)
			)
			return result

		if converted_domain.is_maintenance:
			logger.debug(
				messages.SKIPPED_CHECKING_SITE_S_SUBSCRIPTION_S_1 % (
					self.name, self.subscription.name
				)
			)
			return result

		# retrieve src_ip 
		#(any) H-Sphere site may have different web IP than
		# the corresponding H-Sphere subscription has So, first try to use
		# site's ip address, and if it's not defined, use subscription's IP
		# address.
		src_ip = raw_domain.web_ips.v4 or raw_domain.web_ips.v6\
			 or raw_subscription.ip or raw_subscription.ipv6
		if src_ip is None:
			warnmsg = (
				messages.SETTINGS_DOMAIN_S_SOURCE_SERVER_ARE % (
					self.name
				)
			)
			logger.error(warnmsg)
			result.issues.append(checking.Issue(
				checking.Problem(
					'real_check_web_failure', checking.Problem.WARNING, warnmsg
				),
				messages.RESOLVE_INCONSISTENCY_SOURCE_SERVER))
			return result

		if not self._check_web_ip(result):
			return result

		# protocols
		protocols = ['http']
		if converted_domain.https_enabled:
			protocols.append('https')

		def get_domain_aps_urls(domain, protocol):
			urls = []
			for application in converted_domain.get_direct_aps_applications():
				application_domain_urls = \
					application.get_public_urls()
				urls.extend([
					domain_relative_url
					for aps_protocol, domain_relative_url 
					in application_domain_urls
					if aps_protocol == protocol
				])
			return urls

		web_target_server = self.subscription.web_target_server

		def _get_error_logs(domain_name):
			if web_target_server is not None \
					and not web_target_server.is_windows():
				server = web_target_server.get_hosting_server()
				return server.get_unix_vhost_error_log_files(domain_name)
			else:
				return None

		def _get_target_node_runner():
			if web_target_server is not None:
				return HostingCheckerRunnerAdapter(web_target_server.runner)
			else:
				return None

		dst_ips = [self.subscription.target_web_ip or self.subscription.target_web_ipv6]
		for dst_ip in dst_ips:
			for protocol in protocols:
				result.hosting_check_entities.append(
					parallels.hosting_check.DomainWebService(
						domain_name=self.name, 
						web_server_ip=dst_ip, 
						protocol=protocol, 
						source_web_server_ip=src_ip, 
						aps_domain_relative_urls=get_domain_aps_urls(
							converted_domain, protocol
						),
						runner=_get_target_node_runner(),
						error_logs=_get_error_logs(self.name)
					)
				)
		return result
