from parallels.common.connections.target_servers import TargetServers
from parallels.target_panel_plesk.connections.target_server import \
		PleskTargetServer
from parallels.target_panel_plesk.connections.database_target_server import \
		PleskDatabaseTargetServer
from parallels.common.hosting_check.entity_source.service import \
		TargetServiceInfo
from parallels.common.utils import plesk_utils
from parallels.plesk_api import operator as plesk_ops

class PleskTargetPanel(object):
	def __init__(self):
		self.db_credentials_cache = dict()
		self._plesk_target_server = None

	@property
	def name(self):
		return 'Plesk'

	def has_custom_subscriptions_feature(self):
		"""Whether subscriptions not assigned to plan are allowed"""
		return True

	def has_admin_subscriptions_feature(self):
		"""Whether subscriptions assigned directly to admin are allowed"""
		return True

	def has_reseller_subscriptions_feature(self):
		"""Whether subscriptions assigned directly to reseller are allowed"""
		return True

	def has_no_customer_subscriptions(self):
		"""Whether subscriptions not assigned to customer are allowed
		
		Such subscriptions are assigned directly to admin or reseller
		"""
		return True

	def has_dns_forwarding(self):
		"""Whether panel should support DNS forwarding migration feature"""
		return False

	def transfer_resource_limits_by_default(self):
		"""Whether resource limits should be transferred by default"""
		return True 

	def get_subscription_nodes(self, conn, subscription_target_services, subscription_name):
		databases = {}
		for db_type, db_params in subscription_target_services.db_servers.iteritems():
			if conn.is_windows:
				with conn.main_node_runner() as runner:
					login, password = plesk_utils.get_windows_db_server_credentials(
						runner, db_type, db_params.host
					)
			elif db_params is not None:
				login = db_params.admin
				password = db_params.password
				if login is None or password is None:
					login, password = self.db_credentials_cache.get(
						(db_type, db_params.host), # key
						(None, None) # default
					)
				if login is None or password is None:
					with conn.main_node_runner() as runner:
						login, password = plesk_utils.get_unix_db_server_credentials(
							runner, db_type, db_params.host
						)
						# put to cache
						cache_key = (db_type, db_params.host)
						cache_value = (login, password)
						self.db_credentials_cache[cache_key] = cache_value
			else:
				continue

			databases[db_type] = PleskDatabaseTargetServer(
				conn, db_type, db_params.host, db_params.port,
				login, password, self._get_plesk_target_server(conn)
			)
		return TargetServers(
			web=self._get_plesk_target_server(conn),
			mail=self._get_plesk_target_server(conn),
			database=databases,
			dns=[self._get_plesk_target_server(conn)]
		)

	def get_service_nodes(self, conn):
		service_nodes = [
			TargetServiceInfo(
				service_type='web',
				node=self._get_plesk_target_server(conn)
			),
			TargetServiceInfo(
				service_type='mail',
				node=self._get_plesk_target_server(conn)
			),
			TargetServiceInfo(
				service_type='dns',
				node=self._get_plesk_target_server(conn)
			)
		]
		for result in conn.plesk_api().send(
			plesk_ops.DbServerOperator.Get(
				filter=plesk_ops.DbServerOperator.FilterAll()
			)
		):
			# We can not use the database server until credentials is not
			# set. Example: for postgresql credentials don't set after
			# install.
			if result.data.status == 'CREDENTIALS_NOT_SET':
				continue
			# Check only local database server.
			if result.data.local:
				service_nodes.append(
					TargetServiceInfo(
						service_type=result.data.dbtype,
						node=self._get_plesk_target_server(conn)
					)
				)
		return service_nodes

	def _get_plesk_target_server(self, conn):
		if self._plesk_target_server is None:
			self._plesk_target_server = PleskTargetServer(conn)
		return self._plesk_target_server
