from parallels.core import messages
from parallels.core.actions.base.subscription_backup_action import SubscriptionBackupAction
from parallels.core.actions.utils.logging_properties import LoggingProperties
from parallels.core.dump.entity.password import Password
from parallels.core.reports.model.issue import Issue


class ChangeSysuserPassword(SubscriptionBackupAction):
    """Sysusers may have passwords not valid for current Plesk.
    In this case, change password and inform provider in the end of migration.
    """

    def get_description(self):
        return messages.CHANGE_NONVALID_SYSTEM_USER_PASSWORD

    def get_failure_message(self, global_context, subscription):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        return messages.FAILED_CHANGE_NONVALID_SYSTEM_USER_PASSWORDS % subscription.name

    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):
        return LoggingProperties(info_log=False)

    def _run_subscription_backup(
        self, global_context, subscription, subscription_backup
    ):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        for sysuser in subscription_backup.iter_system_users():
            if not self._password_is_valid(sysuser.password):
                new_password = global_context.password_holder.get('system_user', sysuser.name)
                if sysuser.password is not None:
                    global_context.safe.add_issue_subscription(subscription.name, Issue(
                        'invalid_system_password', Issue.SEVERITY_WARNING,
                        messages.PASSWORD_SYSTEM_USER_S_DOES_NOT % sysuser.name,
                        messages.SYSTEM_USER_S_TRANSFERRED_ANOTHER_PASSWORD % (sysuser.name, new_password)
                    ))
                sysuser.password = Password(password_text=new_password, password_type='plain')

    @staticmethod
    def _password_is_valid(password):
        """Validate password agains Plesk requirements
        Return True if password is valid, False otherwise.
        """
        if password is None:
            return False
        if password.password_type == 'plain':
            for c in password.password_text:
                if any([ord(c) >= 128, c == "'", c == " "]):
                    return False
        return True
