from parallels.core.utils.common import append_if_not_none, is_string, find_only
from parallels.core.utils.paths import web_paths
from parallels.core.utils.paths.copy_web_content import CopyWebContentItem
from parallels.plesk.source.custom import messages
from parallels.plesk.source.custom.hosting_description.converter_to_dump import read_hosting_description_file


class CustomPanelWebFiles(object):
	"""List web files and directories to be copied from custom panel"""

	def list_files_to_copy(self, global_context, subscription):
		"""Make a list of source server directories and files to be transferred.

		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.plesk.source.custom.migrated_subscription.CustomPanelMigratedSubscription
		:rtype: list[parallels.core.utils.paths.copy_web_content.CopyWebContentItem]
		"""
		tocopy = []

		hosting_description_config = global_context.conn.get_hosting_description_config(subscription.model.source)
		hosting_description_data = read_hosting_description_file(hosting_description_config)
		subscription_data = self._get_subscription_hosting_description_data(hosting_description_data, subscription.name)

		append_if_not_none(tocopy, self._convert_hosting_description_items(
			subscription.hosting_description.source_document_root,
			web_paths.WebspaceDocumentRoot(subscription.converted_dump)
		))
		append_if_not_none(tocopy, self._convert_hosting_description_items(
			subscription.hosting_description.source_webspace_root,
			web_paths.WebspaceRoot(subscription.converted_dump)
		))

		for web_files_to_copy in subscription_data.get('web_files', []):
			tocopy.append(CopyWebContentItem(
				source_path=web_paths.AbsolutePath(web_files_to_copy['source']),
				target_path=web_paths.WebspacePathTemplate(
					subscription.converted_dump,
					web_files_to_copy['target']
				),
				exclude=web_files_to_copy.get('exclude', []),
				skip_if_source_not_exists=web_files_to_copy.get('skip_if_source_not_exists', False)
			))

		for addon_domain in subscription.converted_dump.iter_addon_domains():
			addon_domain_hosting_description = subscription.hosting_description.get_addon_domain(addon_domain.name)
			append_if_not_none(tocopy, self._convert_hosting_description_items(
				addon_domain_hosting_description.source_document_root,
				web_paths.SiteDocumentRoot(subscription.converted_dump, addon_domain)
			))

			for addon_domain_web_files_to_copy in addon_domain_hosting_description.iter_web_files():
				tocopy.append(CopyWebContentItem(
					source_path=web_paths.AbsolutePath(addon_domain_web_files_to_copy.source),
					target_path=web_paths.SitePathTemplate(
						subscription.converted_dump,
						addon_domain,
						addon_domain_web_files_to_copy.target
					),
					exclude=addon_domain_web_files_to_copy.exclude,
					skip_if_source_not_exists=addon_domain_web_files_to_copy.skip_if_source_not_exists
				))

		for subdomain in subscription.converted_dump.iter_all_subdomains():
			subdomain_hosting_description = subscription.hosting_description.get_subdomain(subdomain.name)
			append_if_not_none(tocopy, self._convert_hosting_description_items(
				subdomain_hosting_description.source_document_root,
				web_paths.SiteDocumentRoot(subscription.converted_dump, subdomain)
			))

			for subdomain_web_files_to_copy in subdomain_hosting_description.iter_web_files():
				tocopy.append(CopyWebContentItem(
					source_path=web_paths.AbsolutePath(subdomain_web_files_to_copy.source),
					target_path=web_paths.SitePathTemplate(
						subscription.converted_dump,
						subdomain,
						subdomain_web_files_to_copy.target
					),
					exclude=subdomain_web_files_to_copy.exclude,
					skip_if_source_not_exists=subdomain_web_files_to_copy.skip_if_source_not_exists
				))

		return tocopy

	@staticmethod
	def _convert_hosting_description_items(source_value, target_path):
		if source_value is not None:
			if is_string(source_value):
				return CopyWebContentItem(
					source_path=web_paths.AbsolutePath(source_value),
					target_path=target_path
				)
			else:
				return CopyWebContentItem(
					source_path=web_paths.AbsolutePath(source_value['path']),
					target_path=target_path,
					exclude=source_value.get('exclude', [])
				)
		else:
			return None

	@staticmethod
	def _get_subscription_hosting_description_data(hosting_description_data, subscription_name):
		all_subscriptions = [
			subscription for client in hosting_description_data
			for subscription in client.get('subscriptions', [])
		]
		return find_only(
			all_subscriptions, lambda s: s.get('name') == subscription_name,
			messages.FAILED_TO_FIND_SUBSCRIPTION_IN_DUMP % subscription_name
		)