from parallels.core import safe_format
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.reports.model.issue import Issue
from parallels.plesk.source.mail.exceptions import MailMigratorError
from parallels.plesk.source.mail.status_storage import StatusStorage


# noinspection PyAbstractClass
class MailMigrationAction(CommonAction):
    """Base action for all mail migration actions
    """

    def on_exception(self, global_context, exception):
        """Handle unhandled exceptions

        :type global_context: parallels.plesk.source.mail.global_context.MailGlobalMigrationContext
        :type exception: Exception
        :rtype: None
        """
        if self.is_skip_error_reporting():
            return

        if global_context.status_storage is None:
            return

        if global_context.status_storage.get_reporting_mode() == StatusStorage.REPORTING_MODE_SYNC:
            if isinstance(exception, MailMigratorError):
                error_message = exception.error_message
                error_id = exception.error_id
                error_details = exception.error_details
            else:
                error_message = self.get_failure_message(global_context)
                error_id = self.get_error_id()
                error_details = safe_format("{details}", details=exception)

            global_context.status_storage.set_task_status(StatusStorage.STATUS_FAILURE)
            global_context.status_storage.set_task_error(error_id, error_message, error_details)
        elif global_context.status_storage.get_reporting_mode() == StatusStorage.REPORTING_MODE_ASYNC:
            if global_context.migration_list_mail_address_pair is not None:
                if isinstance(exception, MailMigratorError):
                    error_message = exception.error_message
                    error_details = exception.error_details
                else:
                    error_message = self.get_failure_message(global_context)
                    error_details = safe_format("{reason}", reason=exception)

                global_context.status_storage.add_global_issue(
                    global_context.migration_list_mail_address_pair.source_email,
                    global_context.migration_list_mail_address_pair.target_mailname,
                    Issue(
                        'general_error', Issue.SEVERITY_ERROR,
                        error_message,
                        details_text=error_details
                    )
                )

    def is_skip_error_reporting(self):
        """Whether to skip reporting action errors to status file (~ whether errors will be visible in GUI)

        :rtype: bool
        """
        return False

    def get_error_id(self):
        """Get error ID for errors generated inside of the current action.

        :rtype: str | unicode
        """
        return 'general_error'
