import time

from parallels.core import get_logger
from parallels.core.actions.utils.logging_properties import LoggingProperties
from parallels.plesk.source.mail import messages
from parallels.plesk.source.mail.actions.base.mail_migration import MailMigrationAction
from parallels.plesk.source.mail.status_storage import StatusStorage

logger = get_logger(__name__)


class FinalizeTransferMailStatistics(MailMigrationAction):
    """Update statistics for 'transfer-mail' command and save it to file
    """

    _statuses = {
        StatusStorage.STATUS_CANCELLED: "CANCELLED",
        StatusStorage.STATUS_FAILURE: "ERROR_OTHER",
        StatusStorage.STATUS_WARNING: "ERROR_OTHER",
        StatusStorage.STATUS_SUCCESS: "FINISHED_OK",
        StatusStorage.STATUS_IN_PROGRESS: "IN_PROGRESS",
        StatusStorage.ERROR_CONNECT: "ERROR_CONN",
        StatusStorage.ERROR_SECURITY: "ERROR_CONN",
        StatusStorage.ERROR_SECURITY_INVALID_CERTIFICATE: "ERROR_SSL_CERT",
        StatusStorage.ERROR_AUTHENTICATION: "ERROR_AUTH",
        StatusStorage.ERROR_IMAP_HOST_AUTODETECT: "ERROR_IMAP_HOST_AUTODETECT"
    }

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

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

    def get_failure_message(self, global_context):
        """Get message for situation when action failed

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: str | unicode
        """
        return messages.FAILED_ACTION_FINALIZE_TRANSFER_MAIL_STATISTICS

    def is_critical(self):
        """If action is critical or not

        If action is critical and it failed for a subscription, migration tool
        won't run the next operations for the subscription.

        :rtype: bool
        """
        return False

    def get_logging_properties(self):
        """Get how action should be logged to migration tools end-user

        :rtype: parallels.core.actions.utils.logging_properties.LoggingProperties
        """
        return LoggingProperties(info_log=False, compound=False)

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

        Arguments:
        - global_context - registry with different objects that reused among different actions

        :type global_context: parallels.plesk.source.mail.global_context.MailGlobalMigrationContext
        :rtype: bool
        """
        return global_context.statistics_transfer_mail is not None

    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 True

    def run(self, global_context):
        """
        :type global_context: parallels.plesk.source.mail.global_context.MailGlobalMigrationContext
        """
        stat = global_context.statistics_transfer_mail
        stat.status = self._get_status_value(global_context)
        stat.end_time = int(time.time())
        stat.write()

    def _get_status_value(self, global_context):
        """
        :rtype: str | unicode
        """
        if global_context.stop_mark.is_set():
            return self._statuses[StatusStorage.STATUS_CANCELLED]
        elif global_context.status_storage.has_errors():
            if global_context.statistics_transfer_mail.status is not None:
                return self._statuses[global_context.statistics_transfer_mail.status]
            return self._statuses[StatusStorage.STATUS_FAILURE]
        elif global_context.status_storage.has_warnings():
            if global_context.statistics_transfer_mail.status is not None:
                return self._statuses[global_context.statistics_transfer_mail.status]
            return self._statuses[StatusStorage.STATUS_WARNING]
        else:
            if global_context.statistics_transfer_mail.status is not None:
                return self._statuses[global_context.statistics_transfer_mail.status]
            else:
                return self._statuses[StatusStorage.STATUS_SUCCESS]