import logging
import os
from parallels.common.actions.base.common_action import CommonAction
from parallels.common.actions.utils.logging_properties import LoggingProperties
from parallels.common.target_panels import TargetPanels
from parallels.common.utils import plesk_utils
from parallels.common.utils.yaml_utils import read_yaml

logger = logging.getLogger(__name__)


class RestoreApacheRestartInterval(CommonAction):
	def get_description(self):
		return "Restore Apache restart interval"

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		"""
		return "Failed to restore the old Apache restart interval value: %s" % global_context.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.common.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.common.global_context.GlobalMigrationContext
		:rtype: bool
		"""
		return len(self._get_apache_servers(global_context)) > 0

	def run(self, global_context):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		"""
		if global_context.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.common.global_context.GlobalMigrationContext
		:type target_server: parallels.common.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("Restore old Apache restart interval value")
			plesk_utils.set_apache_restart_interval_value(target_server, old_interval_value)
			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.common.global_context.GlobalMigrationContext
		:rtype: set[parallels.common.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):
		"""
		:type global_context: parallels.common.global_context.GlobalMigrationContext
		:type target_server: parallels.common.connections.plesk_server.PleskServer
		"""
		logger.info("Force Apache restart")
		if global_context.target_panel != TargetPanels.PPA:
			with target_server.runner() as runner:
				plesk_utils.restart_plesk_apache(runner, target_server.plesk_dir)
		else:
			for apache_node_id in [1] + global_context.import_api.listServiceNodeIds('ppa_apache'):
				with global_context.conn.target.ppa_unix_node_runner(apache_node_id) as runner:
					plesk_utils.restart_plesk_apache(runner)