from parallels.core import messages
from parallels.core.import_api.import_api import UserAlreadyExistsException, LoginIsInvalidException
from parallels.core.utils.common import safe_string_repr


def plesk_unix_change_sysuser_login(runner, subscription_name, sysuser_login):
	cmd_str = u"/usr/local/psa/admin/plib/api-cli/domain.php --update %s -login %s" % (
		subscription_name.encode('idna'), 
		sysuser_login
	)
	exit_code, stdout_content, stderr_content = runner.sh_unchecked(cmd_str)
	_parse_change_sysuser_login_output(cmd_str, sysuser_login, exit_code, stdout_content, stderr_content)


def plesk_windows_change_sysuser_login(server, subscription_name, sysuser_login):
	with server.runner() as runner:
		cmd_str = ur"%s\bin\domain --update %s -login %s" % (
			server.plesk_dir,
			subscription_name.encode('idna'), sysuser_login
		)
		exit_code, stdout_content, stderr_content = runner.sh_unchecked(cmd_str)
	_parse_change_sysuser_login_output(cmd_str, sysuser_login, exit_code, stdout_content, stderr_content)


def _parse_change_sysuser_login_output(cmd_str, sysuser_login, exit_code, stdout_content, stderr_content):
	if exit_code != 0:
		if u"user %s already exists." % (sysuser_login.lower(),) in stderr_content.lower():
			raise UserAlreadyExistsException()
		elif messages.SOME_FIELDS_ARE_EMPTY_CONTAIN_AN in stderr_content and u"'login'" in stderr_content:
			raise LoginIsInvalidException()
		else:
			raise Exception(
				messages.COMMAND_FAILED_WITH_EXIT_CODE % (
					cmd_str, exit_code, safe_string_repr(stdout_content), safe_string_repr(stderr_content)
				)
			)


def plesk_unix_get_dedicated_app_pool_user(runner, subscription_name):
	get_new_iis_app_user_cmd = \
		u"mysql --silent --skip-column-names -u admin -p`cat /etc/psa/.psa.shadow` psa -e \"%s\"" % (
			_get_dedicated_app_pool_user_query(subscription_name.encode('idna')),
		)
	return runner.sh(get_new_iis_app_user_cmd).strip()


def plesk_windows_get_dedicated_app_pool_user(server, subscription_name):
	get_new_iis_app_user_cmd = \
		ur'%s\admin\bin\dbclient --direct-sql --sql="%s"' % (
			server.plesk_dir, _get_dedicated_app_pool_user_query(subscription_name.encode('idna')),
		)
	with server.runner() as runner:
		lines = runner.sh(get_new_iis_app_user_cmd).strip().split("\n")
	if len(lines) > 1:
		return lines[1].strip()
	else:
		return None


def _get_dedicated_app_pool_user_query(subscription_name):
	return u"SELECT identity FROM domains " + \
		u"JOIN IisAppPools ON IisAppPools.ownerType = 'domain' AND IisAppPools.ownerId = domains.id " + \
		u"WHERE domains.name = '%s'" % (subscription_name,)


def plesk_get_service_plan_database_server_data(panel_server, service_template_id, database_server_type):
	query = \
		u"SELECT " \
		u"DatabaseServers.host as host, " \
		u"DatabaseServers.port as port, " \
		u"DatabaseServers.type as type " \
		u"FROM DatabaseServers JOIN TmplData ON DatabaseServers.id = TmplData.value " \
		u"WHERE TmplData.tmpl_id = %s AND TmplData.element = 'default_server_{database_server_type}' " \
		u"LIMIT 1" % service_template_id

	if panel_server.is_windows():
		command = ur'%s\admin\bin\dbclient --direct-sql --sql="{query}"' % panel_server.plesk_dir
	else:
		command = u"mysql --silent --skip-column-names -u admin -p`cat /etc/psa/.psa.shadow` psa -e \"{query}\""

	with panel_server.runner() as runner:
		lines = runner.sh(
			command.format(
				query=query.format(
					database_server_type=database_server_type
				)
			)
		).split('\n')
		if panel_server.is_windows():
			data_line = lines[1].strip() if len(lines) > 1 else None
		else:
			data_line = lines[0].strip() if len(lines) > 0 else None
		if data_line is not None:
			data = data_line.split()
			if len(data) == 3:
				return {'host': data[0].strip(), 'port': data[1].strip(), 'type': data[2].strip()}
			elif len(data) == 2:
				# port may be empty for MSSQL databases
				return {'host': data[0].strip(), 'port': None, 'type': data[1].strip()}
	return None

