from parallels.core import MigrationNoContextError
from parallels.core.logging import get_logger
from parallels.core.utils.common import format_multiline_list
from parallels.plesk.hosting_description.validate.mode import ValidationMode
from parallels.plesk.source.custom import messages
from parallels.core.actions.base.common_action import CommonAction
from parallels.plesk.hosting_description.converter_to_dump import read_hosting_description_file
from parallels.plesk.hosting_description.validate.overall_validator import HostingDescriptionValidator

logger = get_logger(__name__)


class ValidateHostingDescriptionFiles(CommonAction):
    """Validate all hosting description files"""

    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.ACTION_FAILED_VALIDATE_HOSTING_DESCRIPTION

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

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

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

        :type global_context: parallels.plesk.source.custom.global_context.CustomPanelGlobalMigrationContext
        :rtype: None
        """
        conn = global_context.conn
        """:type conn: parallels.plesk.source.custom.connections.MigratorConnections"""
        for hosting_description_config in conn.iter_hosting_description_configs():
            if hosting_description_config.validation_mode == ValidationMode.SKIP:
                continue

            # If server settings are defined in configuration file, then content will be taken from that server.
            # Otherwise (server settings are not defined in configuration file), content will be taken from
            # target server.
            content_source_server = global_context.conn.get_source_server_by_id(hosting_description_config.source_id)
            if content_source_server is None:
                content_source_server = global_context.conn.target.plesk_server

            hosting_description_data = read_hosting_description_file(
                hosting_description_config,
                ignore_binary_data=False
            )
            database_servers = list(global_context.conn.iter_database_servers())
            errors = HostingDescriptionValidator().validate(
                hosting_description_data, database_servers, content_source_server
            )

            if len(errors) > 0:
                if hosting_description_config.validation_mode == ValidationMode.STOP:
                    error_message = messages.VALIDATION_FAILED_MIGRATION_STOPPED.format(
                        file=hosting_description_config.path, errors=format_multiline_list(errors)
                    )
                    raise MigrationNoContextError(error_message)
                elif hosting_description_config.validation_mode == ValidationMode.WARN:
                    error_message = messages.VALIDATION_FAILED.format(
                        file=hosting_description_config.path, errors=format_multiline_list(errors)
                    )
                    logger.warning(error_message)
            else:
                logger.info(messages.VALIDATION_PASSED.format(file=hosting_description_config.path))
