from parallels.core import MigrationNoContextError
from parallels.core.logging import get_logger
from parallels.core.utils.common import is_run_on_windows
from parallels.core.runners.windows.agent import WindowsAgentRunner
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.actions.utils.logging_properties import LoggingProperties
from parallels.plesk.source.plesk import messages

logger = get_logger(__name__)


class CheckSourceAccountAction(CommonAction):
    """Check that RPC agents on all windows sources executed by built-in administrator"""

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

        :rtype: str
        """
        return messages.ACTION_CHECK_SOURCE_ACCOUNT

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

        This message should contain impact and ways to resolve or work the
        problem around

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

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

    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.core.global_context.GlobalMigrationContext
        :rtype: bool
        """
        return is_run_on_windows()

    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)

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

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

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: None
        """
        for source_id in global_context.source_servers:
            source_server = global_context.conn.get_source_node(source_id)
            with source_server.runner() as runner:
                if not isinstance(runner, WindowsAgentRunner):
                    # check only RPC agent runners
                    continue
                is_configured_manually = runner.remote.is_configured_manually()
                try:
                    result = runner.is_run_by_built_in_administrator()
                except Exception as e:
                    # do not block migration if unable to check administrator account for some reason,
                    # just log error and skip it
                    logger.error(messages.ACTION_CHECK_SOURCE_ACCOUNT_UNABLE.format(
                        source_ip=source_server.ip(),
                        exception=e
                    ))
                    break
                if result:
                    logger.info(
                        messages.ACTION_CHECK_SOURCE_ACCOUNT_BUILT_IN_MANUAL.format(
                            source_ip=source_server.ip()
                        ) if is_configured_manually else
                        messages.ACTION_CHECK_SOURCE_ACCOUNT_BUILT_IN_AUTO.format(
                            source_ip=source_server.ip()
                        )
                    )
                else:
                    raise MigrationNoContextError(
                        messages.ACTION_CHECK_SOURCE_ACCOUNT_NOT_BUILT_IN_MANUAL.format(
                            source_ip=source_server.ip()
                        ) if is_configured_manually else
                        messages.ACTION_CHECK_SOURCE_ACCOUNT_NOT_BUILT_IN_AUTO.format(
                            source_ip=source_server.ip()
                        )
                    )
