import logging
import xml.etree.ElementTree as et
import os

from parallels.common.actions.hosting_settings.transfer_virtual_directories import TransferVirtualDirectoriesBase
from parallels.common.utils.windows_utils import path_join as windows_path_join
from parallels.common.utils.vdir_utils import VirtualDirectoryXMLConverter
from parallels.helm_migrator import helm_utils
from parallels.utils import xml


logger = logging.getLogger(__name__)


class TransferVirtualDirectories(TransferVirtualDirectoriesBase):
	def _get_site_vdirs_xml(self, global_context, subscription, site):
		"""Get virtual directories XML for specified site

		Returned virtual directories XML contains all
		paths according to the target server, not source server.
		Returns XML as string.
		"""
		raw_vdirs_xml = self._get_raw_vdirs_xml(global_context, subscription, site)
		if raw_vdirs_xml is None:
			return None

		converter = self._create_converter(global_context)
		converted_vdirs_xml = converter.convert(subscription, site, raw_vdirs_xml)

		return converted_vdirs_xml

	def _get_raw_vdirs_xml(self, global_context, subscription, site):
		domain_id = helm_utils.get_domain_id_by_name(
			global_context.conn, site.name
		)
		if domain_id is None:
			return None

		vdirs = helm_utils.get_vdir_list(
			global_context.conn, site.name, domain_id
		)
		if vdirs is None:
			return None
		vdirs_node = xml.elem('vdirs')
		vhosts_dir = helm_utils.get_helm_vhost_dir(global_context.conn, subscription.name)
		default_doc = self._get_default_documents(global_context, site.name, domain_id)
		for vdir in vdirs:
			vdir_path = vdir.attrib['physicalpath']
			if vdir_path.startswith('\\'):
				vdir_path = vdir_path[1:]
			if vdir_path.startswith('wwwroot'):
				vdir_path = 'httpdocs' + vdir_path[len('wwwroot'):]

			name = vdir.attrib['path']
			vdirs_node.append(xml.elem('vdir', [], {'name': name[name.rfind(".")+1:],
								'path': windows_path_join(vhosts_dir, vdir_path),
								'authAnonymous': 'true',
								'accessRead': 'true',
								'accessWrite': 'false',
								'accessExecute': 'false',
								'accessScript': 'true',
								'accessSource': 'false',
								'enableDirBrowsing': 'false',
								'enableDefaultDoc': 'true',
								'defaultDoc': default_doc}))

		vhost_node = xml.elem('vhost', [vdirs_node], {'name': site.name,
								'path': windows_path_join(vhosts_dir, 'httpdocs'),
								'authAnonymous': 'true',
								'accessRead': 'true',
								'accessWrite': 'false',
								'accessExecute': 'false',
								'accessScript': 'true',
								'accessSource': 'false',
								'enableDirBrowsing': 'false',
								'enableDefaultDoc': 'true',
								'defaultDoc': default_doc})

		return et.tostring(vhost_node, 'utf-8', 'xml')

	@staticmethod
	def _get_default_documents(global_context, site_name, domain_id):
		try:
			helm_config = global_context.conn.helm.conn_settings
			migration_tool_path = os.path.join(helm_config.migration_tool_dir, helm_config.migration_tool_name)

			with global_context.conn.helm.runner() as helm_runner:
				default_docs = helm_runner.sh('{migration_tool_path} --default-documents {domain_id}',
					dict(migration_tool_path=migration_tool_path, domain_id=domain_id))
		except Exception as e:
			logger.debug(u'Exception:', exc_info=e)
			logger.error(u"Can't get default documents for domain '%s', error is '%s'; skip default documents for this domain. Check the connection to the control server and make sure that the version of Helm installed there is supported by the migrator." % (site_name, e))
			return 'Default.aspx,Default.html,Default.asp,Index.htm,Index.cfm'

		return default_docs

	@staticmethod
	def _create_converter(global_context):
		converter = VirtualDirectoryXMLConverter()
		converter.set_reserved_vdirs(['JRunScripts', 'CFIDE', 'cfdocs', '/'])
		path_converter = helm_utils.PathConverter(global_context)
		converter.set_path_convert_function(path_converter.convert)
		return converter
