from parallels.core.utils.paths import web_paths
from parallels.core.utils.paths.copy_web_content import CopyWebContentItem
from parallels.plesk.source.helm3 import messages
import logging

from parallels.core.utils.common import group_by
from parallels.core.utils import subscription_filter
from parallels.core.actions.content.web.copy_windows_content_base import CopyWindowsWebContentBase
from parallels.core import MigrationError

logger = logging.getLogger(__name__)


class CopyWindowsWebContent(CopyWindowsWebContentBase):
	def filter_subscription(self, global_context, subscription):
		if subscription.is_fake:
			return any(site.is_virtual_hosting for site in subscription.raw_dump.iter_sites())
		else:
			return subscription_filter.windows_with_virtual_hosting(subscription)

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

		Return a list of (source directory -> destination directory) mappings.

		:type global_context: parallels.plesk.source.helm3.global_context.Helm3GlobalMigrationContext
		:type subscription: parallels.core.migrated_subscription.MigratedSubscription
		:rtype: list[parallels.core.utils.paths.copy_web_content.CopyWebContentItem]
		"""
		vhost_name = subscription.name_idn

		tocopy = []
		exclude = []

		for site in subscription.raw_dump.iter_addon_domains():
			if site.hosting_type != 'phosting':
				continue
			vhost_site_name = site.name.encode('idna')
			tocopy.append(
				CopyWebContentItem(
					domain_name=site.name,
					source_path=web_paths.VirtualHostsPath(vhost_site_name + '/wwwroot/'),
					target_path=web_paths.SiteDocumentRoot(subscription.converted_dump, site),
					exclude=[],
					# FTP only subscription may have no wwwroot
					skip_if_source_not_exists=True
				),
			)
			tocopy.append(
				CopyWebContentItem(
					domain_name=site.name,
					source_path=web_paths.VirtualHostsPath(vhost_site_name),
					target_path=web_paths.SitePrivate(subscription.converted_dump, site),
					exclude=['/' + vhost_site_name + '/wwwroot/'],
					skip_if_source_not_exists=False
				),
			)
			exclude.append(vhost_site_name)

		if not subscription.is_fake:
			tocopy.append(
				CopyWebContentItem(
					domain_name=subscription.name,
					source_path=web_paths.VirtualHostsPath(vhost_name + '/wwwroot/'),
					target_path=web_paths.WebspaceDocumentRoot(subscription.converted_dump),
					exclude=exclude,
					# FTP only subscription may have no wwwroot
					skip_if_source_not_exists=True
				),
			)
			tocopy.append(
				CopyWebContentItem(
					domain_name=subscription.name,
					source_path=web_paths.VirtualHostsPath(vhost_name),
					target_path=web_paths.WebspaceMainDomainPrivate(subscription.converted_dump),
					exclude=['/' + vhost_name + '/wwwroot/', '/' + vhost_name + '/SSL/'],
					skip_if_source_not_exists=False
				),
			)
			tocopy.append(
				CopyWebContentItem(
					domain_name=subscription.name,
					source_path=web_paths.VirtualHostsPath(vhost_name + '/SSL/'),
					target_path=web_paths.WebspaceSSLDocumentRoot(subscription.converted_dump),
					exclude=[],
					skip_if_source_not_exists=True
				),
			)

		return tocopy

	def _get_source_vhosts_dir(self, global_context, source_server):
		"""Get directory where virtual hosts data is located.

		:type global_context: parallels.core.global_context.Helm3GlobalMigrationContext
		:rtype: str | None
		"""
		return global_context.helm3_agent.get_vhosts_dir_source(source_server)

	def run(self, global_context, subscription):
		list_files = self._list_files_to_copy(global_context, subscription)
		try:
			files_by_domain_name = group_by(
				list_files,
				lambda x: x.domain_name
			)
			for domain_name, files in files_by_domain_name.iteritems():
				source_web_ip = global_context.migrator.get_domain_content_ip(domain_name)
				web_source_server = global_context.conn.helm3.get_source_server_by_ip(source_web_ip)
				self._copy_files_windows(
					global_context,
					subscription,
					files,
					source_web_ip,
					subscription.web_target_server,
					web_source_server
				)
		except Exception as e:
			logger.debug(messages.LOG_EXCEPTION, exc_info=True)
			raise MigrationError((
				messages.RSYNC_FAILED_COPY_FILES) % (
				subscription.web_source_server.description(),
				subscription.web_target_server.description(),
				str(e)
			))
