from contextlib import contextmanager

from parallels.utils import cached
from parallels.common import run_command
from parallels.common.connections.target_servers import TargetServer
from parallels.common.panel.server.plesk_family import HostingServer
from parallels.common.connections.plesk_server import PleskServer
from parallels.common.utils import session_dir
from parallels.common.utils import plesk_api_utils

class PPATargetServer(TargetServer, PleskServer):

	def __init__(self, conn, ppa_host_id, ip):
		self.conn = conn
		self.ppa_host_id = ppa_host_id
		self.ip_address = ip

		if self.is_windows():
			self._session_dir = session_dir.WindowsSessionDir(
				self.runner, self.conn.windows_session_dir
			)
		else:
			self._session_dir = session_dir.UnixSessionDir(
				self.runner, self.conn.unix_session_dir
			)

	@cached
	def plesk_api(self):
		return self.conn.plesk_api()

	def get_hosting_server(self):
		return HostingServer(self)

	@contextmanager
	def runner(self):
		if self.is_windows():
			with self.conn.ppa_windows_node_runner(self.ppa_host_id) as runner:
				yield runner
		else:
			with self.conn.ppa_unix_node_runner(self.ppa_host_id) as runner:
				yield runner

	@cached
	def is_windows(self):
		"""Determine if POA host is Windows or Linux. Return True for Windows, False for Linux.
		As it is unlikely that this information changes during migration tool execution, we can safely cache it.
		"""
		with self.conn.main_node_runner() as runner:
			return run_command.hcl_is_windows(
				runner,
				self.ppa_host_id,
				self.description()
			)

	@cached
	def description(self):
		return self.conn.get_ppa_node_description(self.ppa_host_id)

	def ip(self):
		return self.ip_address

	@cached
	def ips(self):
		poa_api = self.conn.poa_api()
		ip_addresses = poa_api.getHost(self.ppa_host_id).ip_addresses
		return set([
			ip_info.address 
			for ip_info in ip_addresses
		])

	def session_dir(self):
		return self._session_dir.get_session_dir_path()

	def get_session_file_path(self, filename):
		return self._session_dir.get_file_path(filename)

	@property
	@cached
	def plesk_version(self):
		"""Return a tuple with Plesk server version."""
		version = plesk_api_utils.get_plesk_version(
			self.conn.plesk_api()
		)
		return tuple(map(int, (version.split("."))))

	def __repr__(self):
		return 'PPATargetServer(%s)' % (self.ppa_host_id)

	def __hash__(self):
		return hash(self.ppa_host_id)

	def __eq__(self, another): 
		return isinstance(another, PPATargetServer) and another.ppa_host_id == self.ppa_host_id
