from collections import namedtuple

from parallels.core.utils.common import unused
from parallels.core.utils.restore_hosting_utils import get_restore_hosting_utils


class TargetPanelBase(object):
    @property
    def name(self):
        raise NotImplementedError()

    def has_admin_reseller_plan_feature(self):
        """Whethere admin reseller plans are supported for that target panel migration

        :rtype: bool
        """
        raise NotImplementedError()

    def has_custom_subscriptions_feature(self):
        """Whether subscriptions not assigned to plan are allowed

        :rtype: bool
        """
        raise NotImplementedError()

    def has_admin_subscriptions_feature(self):
        """Whether subscriptions assigned directly to admin are allowed

        :rtype: bool
        """
        raise NotImplementedError()

    def get_default_admin_name(self):
        """
        Return name of user to assign subscription, not assigned to particular user,
        if panel unable to assign subscription to administrator directly, None otherwise
        :rtype: str
        """
        if self.has_admin_subscriptions_feature():
            return None
        raise NotImplementedError()

    def has_reseller_subscriptions_feature(self):
        """Whether subscriptions assigned directly to reseller are allowed

        :rtype: bool
        """
        raise NotImplementedError()

    def has_subscriptions_only(self, global_context):
        """Whether panel have subscriptions only, but not clients, resellers, plans, etc

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: bool
        """
        return False

    def has_resellers(self, global_context):
        """Whether panel has resellers

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: bool
        """
        return True

    def get_default_reseller_name(self, reseller):
        """
        Return name of user to assign reseller subscription, not assigned to particular user,
        if panel unable to assign subscription to reseller directly, None otherwise
        :type reseller: parallels.core.dump.entity.reseller.Reseller
        :rtype: str
        """
        unused(reseller)
        if self.has_reseller_subscriptions_feature():
            return None
        raise NotImplementedError()

    def has_dns_forwarding(self):
        """Whether panel should support DNS forwarding migration feature

        :rtype: bool
        """
        raise NotImplementedError()

    def is_test_dns_forwarding(self):
        """Whether to test DNS forwarding feature on post-migration checks

        :rtype: bool
        """
        return self.has_dns_forwarding()

    def is_transfer_resource_limits_by_default(self):
        """Whether resource limits should be transferred by default

        :rtype: bool
        """
        return True

    def is_remove_coinciding_dns_records(self):
        """Whether DNS records which match domain names withing subscription should be removed
        before these domains could be created in panel

        :rtype: bool
        """
        return True

    def is_encrypted_passwords_supported(self):
        """Whether encrypted passwords (hashes) are supported when creating resellers and clients

        :rtype: bool
        """
        return False

    def get_subscription_target_services(self, global_context, subscription_name):
        """Get location of subscriptions's hosting services on target panel

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription_name: str | unicode
        :rtype: parallels.core.subscription_target_info.TargetServices
        """
        raise NotImplementedError()

    def get_subscription_nodes(self, global_context, subscription_name):
        """Get servers of subscription on target panel

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :type subscription_name: str | unicode
        :rtype: parallels.core.subscription_target_info.TargetServers
        """
        raise NotImplementedError()

    def get_subscription_plesk_node(self, global_context, subscription_name):
        raise NotImplementedError()

    def get_service_nodes(self, conn):
        """Return all service nodes of the panel

        Return list of service nodes to check services during service checks
        List consists of parallels.core.hosting_check.entity_source.service.TargetServiceInfo
        """
        raise NotImplementedError()

    def get_connections(self, global_context):
        """Get target panel connections"""
        raise NotImplementedError()

    def get_hosting_repository(self, global_context):
        """Retrive hosting repository of target panel

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: parallels.core.hosting_repository.model.HostingRepositoryModel
        """
        raise NotImplementedError()

    def get_converter_adapter(self):
        """
        :rtype: parallels.core.converter.adapter.client_subscription_converter.ClientSubscriptionConverterAdapter
        """
        raise NotImplementedError()

    def get_reseller_plan_converter_adapter(self):
        """
        :rtype: parallels.core.converter.adapter.reseller_plan_converter.ResellerPlanConverterAdapter
        """
        raise NotImplementedError()

    def get_hosting_plan_adapter(self, global_context):
        """Retrieve hosting plan adapter

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: parallels.core.converter.business_objects.plans.HostingPlanAdapter
        """
        raise NotImplementedError()

    def get_hosting_check_messages_panel_id(self):
        raise NotImplementedError()

    def check_version(self, global_context):
        """Check that target panel version is ok for migration purposes. Raise MigrationError othewise.

        Raised exception should contain information about supported versions for migration.
        By default, does nothing, override when adding new panel.

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: None
        """
        pass

    @staticmethod
    def get_restore_hosting_utils(plesk_server):
        return get_restore_hosting_utils(plesk_server)

    def get_import_dump_additional_env_vars(self, global_context):
        """Get additional target panel-specific environment variables to pass to pmmcli when importing dump

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: dict[str, str]
        """
        return dict()

    @property
    def sysuser_name_disallowed_chars(self):
        return {' '}


TargetServiceInfo = namedtuple('TargetServiceInfo', (
    'service_type',
    'node'
))
