import ntpath
import logging

from parallels.core.actions.content.web.copy_windows_content_base import CopyWindowsWebContentBase
from parallels.plesk.source.custom import messages
from parallels.core.utils.paths.copy_web_content import BaseWebPathConverter
from parallels.core.utils.paths import web_paths
from parallels.plesk.source.custom.web_files import CustomPanelWebFiles

logger = logging.getLogger(__name__)


class CustomPanelCopyWindowsWebContent(CopyWindowsWebContentBase):
	"""Copy web content from custom panel's Windows server (access to the server was provided in configuration file)"""

	def filter_subscription(self, global_context, subscription):
		"""Check if we should run this action on given subscription or not

		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type subscription: parallels.plesk.source.custom.migrated_subscription.CustomPanelMigratedSubscription
		"""
		return (
			super(CustomPanelCopyWindowsWebContent, self).filter_subscription(global_context, subscription)
			and
			global_context.conn.has_hosting_description_config(subscription.model.source)
		)

	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]
		"""
		return CustomPanelWebFiles().list_files_to_copy(global_context, subscription)

	@staticmethod
	def _get_source_rsync_converter():
		"""Get converter from abstract source path to concrete path for rsync

		:rtype: parallels.core.utils.paths.copy_web_content.BaseWebPathConverter
		"""
		return SourceRsyncVhostWebPathConverter()

	def _get_source_converter(self, global_context, source_server):
		"""Get converter from abstract source path to concrete path

		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:rtype: parallels.core.utils.paths.copy_web_content.BaseWebPathConverter | None
		"""
		return SourceVhostWebPathConverter()


class SourceRsyncVhostWebPathConverter(BaseWebPathConverter):
	"""Class to convert abstract path descriptor to concrete path for rsync on source server"""

	def expand(self, path, server):
		"""Convert abstract path descriptor to concrete absolute path for rsync on source server

		:type path: parallels.core.utils.web_paths.WebHostingPath
		:rtype: str | unicode
		"""
		if isinstance(path, web_paths.AbsolutePath):
			# For custom panel migration, "/cygdrive" is specified as virtual hosts root to have ability to copy
			# files from any absolute path on the source server. So, here we convert absolute path to path
			# relative to "/cygdrive", and prepend section name from rsyncd.conf, which is name 'vhosts'.
			# For example, C:\Windows\System32 will be converted to '/vhosts/c/Windows/System32/', which
			# means '/cygdrive/c/Windows/System32/' for rsync server installed on the source server
			drive, rel_path = ntpath.splitdrive(path.absolute_path)
			return 'vhosts/%s/%s/' % (drive[:1].lower(), rel_path.replace('\\', '/').strip('/'))
		else:
			assert False, messages.UNSUPPORTED_SOURCE_WEB_PATH_TYPE


class SourceVhostWebPathConverter(BaseWebPathConverter):
	"""Class to convert abstract path descriptor to concrete absolute path on source server"""

	def expand(self, path, server):
		"""Convert abstract path descriptor to concrete absolute path on source server

		:type path: parallels.core.utils.web_paths.WebHostingPath
		:rtype: str | unicode
		"""
		if isinstance(path, web_paths.AbsolutePath):
			return path.absolute_path
		else:
			assert False, messages.UNSUPPORTED_SOURCE_WEB_PATH_TYPE