from parallels.plesk.source.helm3 import messages
import logging
import xml.etree.ElementTree as et

import parallels.core.migrator

from parallels.core.utils.common import cached
from parallels.core.utils.migrator_utils import get_package_extras_file_path
from parallels.core import MigrationError


class Helm3Agent:
	logger = logging.getLogger(__name__)

	def __init__(self, server):
		self.server = server
		self._is_deployed_helm3_agent = False

	def _deploy_helm3_agent_lazy(self):
		if not self._is_deployed_helm3_agent:
			with self.server.runner() as runner:
				helm_scripts = [
					"Helm3MigrationAgent.exe", "Helm3Agent.dll",
					"Helm3CompatibilityChecker.exe", "Helm3CompatibilityChecker.html",
					"ForeignMigratorCoreCommon.dll", "ForeignMigratorCoreInterfaces.dll",
					"psa.idna.dll",	"psabackupcommon.dll", "psadumpagent.dll",
					"psadumpschema.dll", "PsaFactory.dll", "adodb.dll"
				]
				for script_name in helm_scripts:
					remote_script_path = self.server.get_session_file_path(script_name)
					runner.upload_file(
						get_package_extras_file_path(parallels.plesk.source.helm3, script_name),
						remote_script_path
					)
				self._is_deployed_helm3_agent = True

	def run(self, args=[]):
		self._deploy_helm3_agent_lazy()
		with self.server.runner() as runner:
			migration_tool_bin = self.server.get_session_file_path(
				' '.join(["Helm3MigrationAgent.exe"] + args)
			)
			return runner.sh(migration_tool_bin).strip()

	def run_unchecked(self, args=[]):
		self._deploy_helm3_agent_lazy()
		with self.server.runner() as runner:
			migration_tool_bin = self.server.get_session_file_path(
				' '.join(["Helm3MigrationAgent.exe"] + args)
			)
			return runner.sh_unchecked(migration_tool_bin)

	@cached
	def get_mail_provider_by_subscription_name(self, name):
		"""Get source mail provider for subscription (for PSAMailBackup)"""
		try:
			return self.run(["--get-mail-provider", name])
		except Exception:
			self.logger.debug(u'Exception:', exc_info=True)
			raise MigrationError(
				messages.CANNOT_DETECT_PROVIDER_TYPE_OF_MAIL % name
			)

	@cached
	def get_domain_diskspace_usage(self, subscription_name, service_type):
		try:
			return float(
				self.run(["--get-diskspace-usage", subscription_name, service_type])
			)
		except Exception:
			self.logger.debug(messages.LOG_EXCEPTION, exc_info=True)
			raise MigrationError(
				messages.CANNOT_GET_DISK_USAGE_FOR_SUBSCRIPTION % subscription_name
			)

	@cached
	def is_fake_domain(self, subscription_name):
		try:
			return self.run(["--is-fake-domain", subscription_name]) == "True"
		except Exception:
			self.logger.debug(messages.LOG_EXCEPTION, exc_info=True)
			raise MigrationError(
				messages.CANNOT_DETECT_IF_SUBSCRIPTION_IS_FAKE % subscription_name
			)

	@cached
	def get_service_ips(self, domain_name, service_type_id):
		try:
			service_ips = []
			exit_code, stdout, _ = self.run_unchecked(
				["--get-service-ips", domain_name, service_type_id]
			)
			if exit_code == 1:
				return []
			elif exit_code != 0:
				raise MigrationError(
					messages.CANNOT_GET_IP_ADDRESSES_FOR_SUBSCRIPTION_SERVICE_IPS_COMMAND % (domain_name, exit_code)
				)
			xml_service_ips = et.fromstring(stdout.strip())
			for ip in xml_service_ips.findall("ip-address"):
				service_ips.append(ip.attrib['ip'])

			return service_ips
		except NoServiceIpHelmDatabase:
			raise
		except Exception:
			self.logger.debug(messages.LOG_EXCEPTION, exc_info=True)
			raise MigrationError(
				messages.CANNOT_GET_IP_ADDRESSES_FOR_SUBSCRIPTION % domain_name
			)
	@cached
	def get_server_ips(self, server_name):
		"""Return server ip with additional ips.
		@param server_name - server host name for which find ips
		"""
		try:
			server_ips = []
			xml_server_ips = et.fromstring(
				self.run(["--get-server-ips", server_name])
			)
			for ip in xml_server_ips.findall("ip-address"):
				server_ips.append(ip.attrib['ip'])

			return server_ips
		except Exception:
			self.logger.debug(messages.LOG_EXCEPTION, exc_info=True)
			raise MigrationError(
				messages.CANNOT_GET_IP_ADDRESSES_FOR_SERVER % server_name
			)

	@cached
	def get_vhosts_dir_source(self, server):
		"""Directory where virtual hosts reside on source"""
		try:
			vhost_dir = self.run(["--get-vhost-dir", server.ip()])
			if vhost_dir == "":
				return None
			else:
				return vhost_dir
		except Exception:
			self.logger.debug(messages.LOG_EXCEPTION, exc_info=True)
			raise MigrationError(
				messages.CANNOT_DETECT_SOURCE_VHOST_DIR % server.ip()
			)


class NoServiceIpHelmDatabase(MigrationError):
	pass
