import logging
import xml.etree.ElementTree as et

import parallels.common.migrator

from parallels.utils import cached
from parallels.common.utils.migrator_utils import get_package_extras_file_path
from parallels.common 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:
				for script_name in ["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"]:
					remote_script_path = self.server.get_session_file_path(script_name)
					runner.upload_file(
						get_package_extras_file_path(parallels.helm3_migrator, 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 as e:
			self.logger.debug(u'Exception:', exc_info=e)
			raise MigrationError(
				"Can't detect provider type of mail services for subscription '%s'." % 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 as e:
			self.logger.debug(u'Exception:', exc_info=e)
			raise MigrationError(
				"Can't get diskspace usage for subscription '%s'." % subscription_name
			)

	@cached
	def is_fake_domain(self, subscription_name):
		try:
			return self.run(["--is-fake-domain", subscription_name]) == "True"
		except Exception as e:
			self.logger.debug(u'Exception:', exc_info=e)
			raise MigrationError(
				"Can't detect if subscription '%s' fake or not.""" % 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(
					"Can't get IP addresses for subscription '%s'. Get service ips command return {%s} exit code." % (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 as e:
			self.logger.debug(u'Exception:', exc_info=e)
			raise MigrationError(
				"Can't get IP addresses for subscription '%s'.""" % 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 as e:
			self.logger.debug(u'Exception:', exc_info=e)
			raise MigrationError(
				"Can't get IP addresses for server '%s'.""" % 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 as e:
			self.logger.debug(u'Exception:', exc_info=e)
			raise MigrationError(
				"Can't detect source vhost dir for server with ip '%s'." % server.ip()
			)


class NoServiceIpHelmDatabase(MigrationError):
	pass
