import ntpath

from parallels.core.logging import get_logger
from parallels.core.actions.hosting_settings.transfer_error_documents import TransferErrorDocumentsBase
from parallels.core.utils import plesk_utils
from parallels.core.utils.windows_utils import normalize_path
from parallels.plesk.source.plesk.plesk_utils import get_vdirs_dict, source_websrvmng_lock
from parallels.plesk.source.plesk.plesk_utils import PathConverter
from parallels.core.utils.error_docs_utils import ErrorDocumentsXMLConverter
from parallels.plesk.source.plesk import messages

logger = get_logger(__name__)


class TransferErrorDocuments(TransferErrorDocumentsBase):
    def filter_subscription(self, global_context, subscription):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        if (
                subscription.web_target_server.is_windows()
                and subscription.web_target_server.get_plesk_version() >= (18, 0, 31)
        ):
            logger.finfo(
                messages.SKIP_ERROR_DOCUMENTS_FOR_SUBSCRIPTION_TARGET_18_0_31_OR_ABOVE,
                subscription=subscription.name
            )
            return False

        return super(TransferErrorDocuments, self).filter_subscription(global_context, subscription)

    def _get_site_error_documents(self, global_context, subscription, site):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        with source_websrvmng_lock:
            raw_error_documents = plesk_utils.get_error_documents(
                subscription.web_source_server, site.name
            )
        converter = self._create_converter()
        converted_error_documents = converter.convert(subscription, site, raw_error_documents)

        return converted_error_documents

    def _get_site_vdir_error_documents(self, global_context, subscription, site):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription: parallels.core.migrated_subscription.MigratedSubscription
        """
        site_www_roots = set()
        for domain in subscription.converted_dump.iter_domains():
            if domain.www_root is not None:
                site_www_roots.add(normalize_path(ntpath.join(
                    subscription.web_target_server.vhosts_dir, subscription.name_idn, domain.www_root
                )))

        vdirs_dict = get_vdirs_dict(global_context, subscription, site)

        error_docs = {}
        converter = self._create_converter()
        for vdir, path in vdirs_dict.items():
            if normalize_path(path) in site_www_roots:
                logger.debug(messages.SKIP_ERROR_DOCUMENTS_FOR_VDIR_IN_WEB_ROOT.format(
                    directory=vdir, path=path
                ))
                continue

            with source_websrvmng_lock:
                raw_error_docs = plesk_utils.get_error_documents(
                    subscription.web_source_server, site.name, vdir
                )
            converted_error_docs = converter.convert(subscription, site, raw_error_docs)
            error_docs[vdir] = converted_error_docs

        return error_docs

    @staticmethod
    def _create_converter():
        converter = ErrorDocumentsXMLConverter()
        path_converter = PathConverter()
        converter.set_path_convert_function(path_converter.convert)
        return converter
