from parallels.core import messages
from parallels.core.actions.base.base_action \
	import BaseAction
from parallels.core.actions.utils.logging_properties import LoggingProperties


class CompoundAction(BaseAction):
	"""Action in workflow which consists of other actions"""
	def __init__(self, description=None, logging_properties=None, run_by_subscription=True):
		self._actions = []
		self._description = description
		if logging_properties is not None:
			self._logging_properties = logging_properties
		else:
			self._logging_properties = LoggingProperties()
		self._run_by_subscription = run_by_subscription

	def get_description(self):
		return self._description

	def get_logging_properties(self):
		return self._logging_properties

	@property
	def run_by_subscription(self):
		return self._run_by_subscription

	def insert_action(self, name, action, after=None, before=None):
		self.insert_actions(
			[(name, action,)], after=after, before=before
		)

	def remove_action(self, name):
		self.remove_actions([name])

	def replace(self, name, action):
		new_actions = []
		for existing_name, existing_action in self._actions:
			if name == existing_name:
				new_actions.append((name, action))
			else:
				new_actions.append((existing_name, existing_action))

		self._actions = new_actions

	def insert_first_action(self, name, action):
		"""
		Insert action to the first position

		:param name: action id(name),
		:param action: action object
		:return: None
		"""
		self._actions.insert(0, (name, action))

	def insert_actions(self, actions, after=None, before=None):
		"""Insert multiple actions into workflow

		:param actions: list of actions - tuples (action id, action object)
		:param after: string id of action, all actions will be put after that action
		:param before: string id of action, all actions will be put before that action
		:return: None

		'after' and 'before' parameters are mutually exclusive
		"""
		assert after is None or before is None
		i = 0
		name = None
		for i, (name, _) in enumerate(self._actions):
			if name == after:
				break
			if name == before:
				i -= 1
				break

		if after is not None and name != after:
			raise Exception(messages.FAILED_FIND_ACTION_S_AFTER_WHICH % after)
		if before is not None and name != before:
			raise Exception(messages.FAILED_FIND_ACTION_S_BEFORE_WHICH % before)

		for j, action in enumerate(actions):
			self._actions.insert(i + j + 1, action)

	def remove_actions(self, names):
		new_actions = []
		for name, action in self._actions:
			if name not in names:
				new_actions.append((name, action))
		self._actions = new_actions

	def get_action(self, name):
		return dict(self._actions)[name]

	def get_all_actions(self):
		return self._actions

	def get_path(self, path):
		current = self
		for item in path.split('/'):
			current = current.get_action(item)
		return current
