import logging

from parallels.core import CommandExecutionError
from parallels.ppa.utils import poa_utils
from parallels.core.utils.common import strip_multiline_spaces, default
from parallels.ppa import messages
from parallels.core.utils.steps_profiler import sleep

logger = logging.getLogger(__name__)


class HclRunnerException(CommandExecutionError):
	pass


def hcl_execute_multiple_attempts(run_function, host, command, max_attempts=5, interval_between_attempts=10):
	for attempt in range(0, max_attempts):
		try:
			result = run_function()
			if attempt > 0:
				logger.info(
					messages.COMMAND_EXECUTED_AFTER_ATTEMPTS.format(
						command=command, host=host, attempts=attempt+1
					)
				)
			return result
		except HclRunnerException as e:
			logger.debug(messages.LOG_EXCEPTION, exc_info=True)
			if attempt >= max_attempts - 1:
				raise e
			else:
				logger.error(
					messages.COMMAND_EXECUTION_RETRY.format(
						interval_between_attempts=interval_between_attempts
					)
				)
				sleep(interval_between_attempts, messages.SLEEP_RETRY_COMMAND_EXECUTION)


def hcl_is_windows(ppa_runner, host_id, host_description=None):
	"""Hack to detect service node platform"""

	host_description = default(host_description, messages.DEFAULT_PPA_HOST_DESCRIPTION % host_id)
	windows_pattern = "User '' does not exist"
	command = 'cmd /c REM'

	def run_func():
		# REM - command used for comments in batch file; does nothing, has no output.
		hcl = poa_utils.Hcl(ppa_runner)
		try:
			exit_code, stdout, stderr = hcl.windows_exec_unchecked(host_id, command, 'utf-8')
			if exit_code != 0:
				# looks like Windows, but there are some problems executing the command,
				# so raise HclRunnerException which means - try again
				raise HclRunnerException(
					strip_multiline_spaces(messages.FAILED_DETECT_OS_NODE_COMMAND_COMMAND).format(
						stderr=stderr,
						stdout=stdout,
						command=command,
						host_id=host_id,
						host_description=host_description,
						hcl_script=hcl.get_windows_hcl_script(command),
						windows_pattern=windows_pattern
					),
					stdout, stderr,
					host_description=host_description,
				)
			# no errors occurred, so that is Windows
			return True
		except poa_utils.HclPleskdCtlNonZeroExitCodeError as e:
			if windows_pattern in e.stdout or windows_pattern in e.stderr:
				return False
			else:
				# looks like a problem communicating the node, or something else unexpected - try again
				raise HclRunnerException(
					strip_multiline_spaces(messages.FAILED_DETECT_OS_NODE_COMMAND_COMMAND_1).format(
						stderr=e.stderr,
						stdout=e.stdout,
						command=command,
						host_id=host_id,
						host_description=host_description,
						hcl_script=hcl.get_windows_hcl_script(command),
						windows_pattern=windows_pattern
					),
					e.stdout, e.stderr,
					host_description=host_description,
					cause=e
				)

	return hcl_execute_multiple_attempts(run_func, host_description, command)
