from parallels.core import MigrationError
from parallels.core.utils.common_constants import WINDOWS_REMOTE_TARGET_DEFAULT_SESSION_DIR
from parallels.ppa import messages
from parallels.plesk.config import PLESK_URL_DEFAULTS
from parallels.core.migrator_config import read_ssh_auth
from parallels.plesk.config import TargetPleskConfigBase
from parallels.core.utils.common.ip import is_ipv6, is_ipv4
from parallels.core.utils.config_utils import ConfigSection, read_http_connection_settings, HttpConnectionSettings

POA_URL_DEFAULTS = dict(
	protocol='https',
	port=8440,
	path='/RPC2'
)


class TargetPPAConfig(TargetPleskConfigBase):
	def __init__(
		self, ip, is_local, ssh_auth, poa_api, plesk_api, unix_session_dir, windows_session_dir,
		cligate_ip=None, webmail_ipv4=None, apache_restart_interval=None
	):
		super(TargetPPAConfig, self).__init__(
			ip, is_local, plesk_api, unix_session_dir, windows_session_dir, cligate_ip, apache_restart_interval
		)
		self._ssh_auth = ssh_auth
		self._poa_api = poa_api
		self._webmail_ipv4 = webmail_ipv4

	@property
	def ssh_auth(self):
		return self._ssh_auth

	@property
	def poa_api(self):
		return self._poa_api

	@property
	def is_local(self):
		"""If target server is local or remote
		
		Local server means that migrator works on the target node, remote means
		that migrator's node and target node are different servers
		"""
		# always false, local execution on Unix target node is not supported
		# yet, we always execute commands by SSH
		return self.ssh_auth is None

	@property
	def webmail_ipv4(self):
		return self._webmail_ipv4


def _read_poa_connection_settings(section):
	from urlparse import urlparse, urlunparse

	s = read_http_connection_settings(section)
	
	# Put username and password to URL.
	scheme, host, path, params, query, fragment = urlparse(s.url)
	host = '%s:%s@%s' % (s.auth.username, s.auth.password, host)
	url = urlunparse((scheme, host, path, params, query, fragment))

	return HttpConnectionSettings(url=url, auth=s.auth)


def read_ppa_settings(config, section_name, webmail_ipv4_required=False, default_apache_restart_interval='1800'):
	"""
	:rtype: parallels.ppa.config.TargetPPAConfig
	"""
	section = ConfigSection(config, section_name)

	ip = section['ip']
	is_local = section.getboolean('is-local', True)
	if is_ipv6(ip):
		raise MigrationError(
			messages.PPA_API_DOES_NOT_WORK_OVER % ip
		)
	cligate_ip = section.get('cligate-ip')

	ssh_auth = read_ssh_auth(section, required=False)

	ppa_settings = dict(
		host=ip,
		username=config.get(section_name, 'panel-username'),
		password=config.get(section_name, 'panel-password'),
	)
	poa_api = _read_poa_connection_settings(
		section.prefixed('poa-').with_defaults(dict(POA_URL_DEFAULTS, **ppa_settings))
	)
	plesk_api = read_http_connection_settings(
		section.prefixed('plesk-').with_defaults(dict(PLESK_URL_DEFAULTS, **ppa_settings))
	)
	unix_session_dir = section.get('unix-session-dir', '/tmp')
	windows_session_dir = section.get('windows-session-dir', WINDOWS_REMOTE_TARGET_DEFAULT_SESSION_DIR)

	webmail_ipv4 = section.get('webmail-ip')

	if webmail_ipv4_required:
		if webmail_ipv4 is None:
			raise MigrationError(
				messages.WEBMAIL_IP_ADDRESS_NOT_SPECIFIED
			)
		if not is_ipv4(webmail_ipv4):
			raise MigrationError(
				messages.WEBMAIL_IP_ADDRESS_INVALID % webmail_ipv4
			)

	apache_restart_interval = section.get('apache-restart-interval', default_apache_restart_interval)

	return TargetPPAConfig(
		ip=ip, is_local=is_local, ssh_auth=ssh_auth, poa_api=poa_api, plesk_api=plesk_api,
		unix_session_dir=unix_session_dir, windows_session_dir=windows_session_dir,
		cligate_ip=cligate_ip, webmail_ipv4=webmail_ipv4,
		apache_restart_interval=apache_restart_interval
	)