from parallels.ppa.source.helm4 import messages
import logging
import xml.etree.ElementTree as et
import os

from parallels.core.actions.hosting_settings.transfer_virtual_directories import TransferVirtualDirectoriesBase
from parallels.core.utils.windows_utils import path_join as windows_path_join
from parallels.core.utils.vdir_utils import VirtualDirectoryXMLConverter
from parallels.ppa.source.helm4 import helm_utils
from parallels.core.utils.common 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(messages.LOG_EXCEPTION, exc_info=True)
			logger.error(messages.CANNOT_GET_DEFAULT_DOCUMENTS_FOR_DOMAIN % (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
