from parallels.core import messages
import logging
import os
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.actions.utils.logging_properties import LoggingProperties
from parallels.core.utils import plesk_utils
from parallels.core.utils.yaml_utils import read_yaml

logger = logging.getLogger(__name__)


class RestoreApacheRestartIntervalBase(CommonAction):
	def get_description(self):
		return messages.RESTORE_APACHE_RESTART_INTERVAL

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		"""
		return messages.FAILED_RESTORE_OLD_APACHE_RESTART_INTERVAL % (
			global_context.conn.target.settings.apache_restart_interval
		)

	def is_critical(self):
		"""If action is critical or not

		If action is critical and it failed, migration tool won't run the next operations.

		:rtype: bool
		"""
		return False

	def get_logging_properties(self):
		"""Get how action should be logged to migration tools end-user

		:rtype: parallels.core.actions.utils.logging_properties.LoggingProperties
		"""
		return LoggingProperties(compound=False)

	def filter_action(self, global_context):
		"""Check whether we should run this action or not.

		Arguments:
		- global_context - registry with different objects that reused among different actions

		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:rtype: bool
		"""
		return len(self._get_apache_servers(global_context)) > 0

	def run(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		"""
		if global_context.conn.target.settings.apache_restart_interval == 'none':
			return

		for target_server in self._get_apache_servers(global_context):
			self.restore_apache_restart_interval(global_context, target_server)

	def restore_apache_restart_interval(self, global_context, target_server):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type target_server: parallels.core.connections.target_servers.TargetServer
		"""
		old_interval_value = read_yaml(
			global_context.session_files.get_path_to_apache_restart_interval(target_server.ip()),
			True,
			None
		)
		if old_interval_value is not None:
			logger.debug(messages.RESTORE_OLD_APACHE_RESTART_INTERVAL_VALUE)
			plesk_utils.set_apache_restart_interval_value(target_server, old_interval_value)
			if (
				'live-migration' not in global_context.config.options('GLOBAL') or
				not global_context.config.getboolean('GLOBAL', 'live-migration')
			):
				logger.info(messages.FORCE_APACHE_RESTART)
				self._restart_apache(global_context, target_server)
			os.remove(global_context.session_files.get_path_to_apache_restart_interval(target_server.ip()))

	@staticmethod
	def _get_apache_servers(global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:rtype: set[parallels.core.connections.target_servers.TargetServer]
		"""
		return {
			subscription.panel_target_server for subscription in global_context.iter_all_subscriptions()
			if subscription.panel_target_server and not subscription.panel_target_server.is_windows()
		}

	@staticmethod
	def _restart_apache(global_context, target_server):
		"""Restart Apache on target panel

		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type target_server: parallels.core.connections.plesk_server.PleskServer
		"""
		raise NotImplementedError()


class RestoreApacheRestartIntervalPlesk(RestoreApacheRestartIntervalBase):
	@staticmethod
	def _restart_apache(global_context, target_server):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:type target_server: parallels.core.connections.plesk_server.PleskServer
		"""
		with target_server.runner() as runner:
			plesk_utils.restart_plesk_apache(runner, target_server.plesk_dir)
