from parallels.core.logging import get_logger
from parallels.core.reports.utils import log_issues
from parallels.plesk.source.web import messages
from parallels.plesk.source.web.actions.base.site_migration import SiteMigrationAction

logger = get_logger(__name__)


# noinspection PyAbstractClass
class FolderAction(SiteMigrationAction):
    """Base action for migrated databases
    """

    def filter_action(self, global_context):
        """Check whether we should run this action or not. By default True - action should be executed.

        :type global_context: parallels.plesk.source.web.global_context.WebGlobalMigrationContext
        :rtype: bool
        """
        return len(global_context.list_all_migrated_folders()) > 0

    def run(self, global_context):
        """Run action

        :type global_context: parallels.plesk.source.web.global_context.WebGlobalMigrationContext
        :rtype: None
        """
        action = self.__class__

        for application in global_context.list_migrated_applications():
            safe_object_app = global_context.site_objects_safe.get_application(application)

            if not all(safe_object_app.is_action_successful(a) for a in self.get_pre_requirement_actions()):
                logger.finfo(messages.LOG_SKIP_EXECUTE_FOR_OBJECT, object_description=application.description())
                continue

            logger.finfo(messages.LOG_EXECUTE_FOR_OBJECT, object_description=application.description())

            for folder in application.folders:
                failure_message = self.get_failure_message_for_folder(global_context, folder)
                if failure_message is None:
                    failure_message = self.get_failure_message(global_context)

                with safe_object_app.try_safe(failure_message, action=action):
                    issues = self.run_for_folder(global_context, folder)
                    log_issues(issues)
                    if issues is not None:
                        for issue in issues:
                            safe_object_app.add_issue(issue, action=action)

            safe_object_app.set_executed(action)

        for folder in global_context.list_independent_migrated_folders():
            safe_object_folder = global_context.site_objects_safe.get_folder(folder)

            if not all(safe_object_folder.is_action_successful(a) for a in self.get_pre_requirement_actions()):
                logger.finfo(messages.LOG_SKIP_EXECUTE_FOR_OBJECT, object_description=folder.description())
                continue

            logger.finfo(messages.LOG_EXECUTE_FOR_OBJECT, object_description=folder.description())

            failure_message = self.get_failure_message_for_folder(global_context, folder)
            if failure_message is None:
                failure_message = self.get_failure_message(global_context)

            with safe_object_folder.try_safe(failure_message, action=action):
                issues = self.run_for_folder(global_context, folder)
                log_issues(issues)
                if issues is not None:
                    for issue in issues:
                        safe_object_folder.add_issue(issue, action=action)

            safe_object_folder.set_executed(action)

    def get_failure_message_for_folder(self, global_context, folder):
        """Get message for situation when action failed for specific folder

        :type global_context: parallels.plesk.source.web.global_context.WebGlobalMigrationContext
        :type folder: parallels.plesk.source.web.migrated_folder.MigratedFolder
        :rtype: str | unicode | None
        """
        return None

    def run_for_folder(self, global_context, folder):
        """Run action for single migrated folder

        :type global_context: parallels.plesk.source.web.global_context.WebGlobalMigrationContext
        :type folder: parallels.plesk.source.web.migrated_folder.MigratedFolder
        :rtype: list[parallels.core.reports.model.issue.Issue] | None
        """
        raise NotImplementedError()
