from parallels.core.utils.common import ip as ip_utils
from parallels.core.utils.common import if_not_none
from parallels.ppa.utils import poa_utils
from parallels.core.connections.database_server import DatabaseServer
from parallels.ppa.connections.target_server import PPATargetServer


class PPADatabaseTargetServer(DatabaseServer):
	"""PPA target database server, accessed from PPA service node or PPA management node

	For database servers located on PPA service node, we access them by POA HCL protocols.

	For external databases, we access them with the help of PPA management node. Still that is not recommended as
	management node could not have all necessary utilities and libraries. Consider to use
	parallels.core.connections.database_server.ExternalDatabaseServer for that case instead.
	"""

	def __init__(self, conn, db_type, host, port, user, password):
		"""
		:type conn: parallels.ppa.connections.target_connections.PPATargetConnections
		"""
		self._db_type = db_type
		self._host = host
		self._port = port
		self._user = user
		self._password = password
		self._conn = conn
		self._ip = self._detect_ip()

		try:
			self.ppa_host_id = if_not_none(
				self._ip,
				lambda ip: poa_utils.get_host_id_by_ip(self._conn.poa_api(), ip)
			)
			self._panel_server = PPATargetServer(self._conn, self.ppa_host_id, self._ip)
		except poa_utils.HostNotFoundException:
			# database server with such IP address is not a PPA service node, 
			# so we consider that is an external database server
			self.ppa_host_id = None
			# as it is controlled by PPA management node, use it as panel server
			self._panel_server = self._conn.plesk_server

	def type(self):
		return self._db_type

	def host(self):
		return self._host

	def port(self):
		return self._port

	def user(self):
		return self._user

	def password(self):
		return self._password

	@property
	def panel_server(self):
		return self._panel_server

	@property
	def physical_server(self):
		if self.ppa_host_id is not None:
			# If we have direct access to the server by POA protocols - use it
			return PPATargetServer(self._conn, self.ppa_host_id, self._ip)
		else:
			# Otherwise, this database server is external - return None
			return None

	@property
	def mysql_bin(self):
		return 'mysql'

	@property
	def plesk_dir(self):
		return self._panel_server.plesk_dir

	def _detect_ip(self):
		"""Detect IP address by hostname"""
		if self.host() == 'localhost':
			# 'localhost' for database server in PPA means PPA management node
			return self._conn.main_node_ip
		else:
			# host may contain MS SQL instance name, e.g. 10.50.52.100\MSSQLSERVER2008
			return ip_utils.resolve(self.host().split('\\')[0])