from parallels.core import messages, safe_format
from parallels.core.actions.base.action_pointer import ActionPointer
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.actions.base.compound_action import CompoundAction
from parallels.core.actions.base.condition_action_pointer import ConditionActionPointer
from parallels.core.actions.base.entry_point_action import EntryPointAction
from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.core.registry import Registry
from parallels.core.utils.common import is_empty


class PrintWorkflow(CommonAction):
    def get_description(self):
        """Get short description of action as string

        :rtype: str | unicode
        """
        return messages.PRINT_WORKFLOW_ACTION_DESCRIPTION

    def get_failure_message(self, global_context):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        """
        return messages.PRINT_WORKFLOW_ACTION_FAILURE

    def run(self, global_context):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        """
        workflow = Registry.get_instance().get_workflow()
        for entry_point_id in workflow.get_entry_points():
            print
            print(safe_format(
                "******************** Command: {entry_point} ********************",
                entry_point=entry_point_id
            ))
            entry_point = workflow.get_entry_point(entry_point_id)
            self._print_action(entry_point, entry_point_id)

    def _print_action(self, action, action_id=None, level=0):
        if isinstance(action, ActionPointer):
            action = action.resolve()
        if isinstance(action, ConditionActionPointer):
            print(self._format_action(action, action_id, level))
        elif isinstance(action, EntryPointAction):
            for child_action_id, child_action in action.get_all_actions():
                self._print_action(child_action, child_action_id, level + 1)
        elif isinstance(action, CompoundAction):
            print(self._format_action(action, action_id, level))
            for child_action_id, child_action in action.get_all_actions():
                self._print_action(child_action, child_action_id, level + 1)
        elif isinstance(action, SubscriptionAction) or isinstance(action, CommonAction):
            print(self._format_action(action, action_id, level))

    @staticmethod
    def _format_action(action, action_id, level):
        """
        :rtype: str | unicode
        """
        indent = '    ' * level

        action_type = "Unknown"
        action_description = "Unknown"

        if isinstance(action, ConditionActionPointer):
            action_type = "Condition action pointer"
            action_description = action.__class__.__name__
        elif isinstance(action, CompoundAction):
            action_type = "Compound action"
            action_description = action.get_description()
        elif isinstance(action, SubscriptionAction):
            action_type = "Per-subscription action"
            action_description = action.get_description()
        elif isinstance(action, CommonAction):
            action_type = "Common action"
            action_description = action.get_description()

        if not is_empty(action_description):
            return safe_format(
                "{indent}[{action_type}][{action_id}] {action_description}",
                indent=indent,
                action_type=action_type, action_id=action_id, action_description=action_description
            )
        else:
            return safe_format(
                "{indent}[{action_type}][{action_id}] {action_id}",
                indent=indent,
                action_type=action_type, action_id=action_id
            )
