from collections import namedtuple
from .. import core
from parallels.core.utils.common.xml import seq, text_elem, elem, list_elem

ResellerPlanInfo = namedtuple('ResellerPlanInfo', ('plan_id', 'name',))
ResellerPlanLimits = namedtuple('ResellerPlanLimits', (
    'overuse',
    'oversell',
    'limits'  # list of ResellerPlanLimit
))
ResellerPlanLimit = namedtuple('ResellerPlanLimit', ('name', 'value'))
ResellerPlanPermission = namedtuple('ResellerPlanPermission', ('name', 'value'))
ResellerPlanApsPackage = namedtuple('ResellerPlanApsPackage', (
    # str | unicode
    'name',
    # str | unicode
    'value',
))


class ResellerPlanOperator(object):
    FilterAll = core.FilterAll
    FilterByName = core.declare_filter('FilterByName', 'name')

    class Get(core.operation_with_filter('Get')):
        operator_name = 'reseller-plan'
        operation_name = 'get'
        min_api_version = '1.6.3.0'
        max_api_version = None

        @staticmethod
        def data_xml():
            return seq()

        @classmethod
        def parse(cls, elem):
            return [core.Result.parse(r, cls._parse_data) for r in elem.findall('result')]

        @classmethod
        def _parse_data(cls, elem):
            plan_id = int(elem.findtext('id'))
            name = elem.findtext('name')
            return ResellerPlanInfo(plan_id=plan_id, name=name)

    class Add(core.operation('Add', ('name', 'limits', 'permissions'))):
        operator_name = 'reseller-plan'
        operation_name = 'add'
        min_api_version = '1.6.3.0'
        max_api_version = None

        def inner_xml(self):
            return seq(
                text_elem('name', self.name),
                self._limits_xml(),
                self._permissions_xml(),
            )

        def _limits_xml(self):
            if self.limits.oversell is not None or self.limits.overuse is not None:
                resource_policy = [
                    elem('resource-policy', seq(
                        text_elem('oversell', self.limits.oversell),
                        text_elem('overuse', self.limits.overuse),
                    ))
                ]
            else:
                resource_policy = []

            limits = [
                elem('limit', [text_elem('name', limit.name), text_elem('value', limit.value)])
                for limit in self.limits.limits
            ]

            return elem('limits', resource_policy + limits)

        def _permissions_xml(self):
            return list_elem('permissions', [
                elem('permission', [text_elem('name', permission.name), text_elem('value', permission.value)])
                for permission in self.permissions
            ])

        @classmethod
        def parse(cls, elem):
            return core.Result.parse(elem.find('result'))

    class EnableApsFilter(core.operation_with_filter('EnableApsFilter')):
        operator_name = 'reseller-plan'
        operation_name = 'enable-aps-filter'
        min_api_version = '1.6.3.0'
        max_api_version = None

        @classmethod
        def parse(cls, elem):
            return core.Result.parse(elem.find('result'))

    class AddPackage(core.operation_with_filter('AddPackage', ('packages',))):
        operator_name = 'reseller-plan'
        operation_name = 'add-package'
        min_api_version = '1.6.3.0'
        max_api_version = None

        def data_xml(self):
            return [
                elem('package', [
                    text_elem('name', package.name),
                    text_elem('value', package.value)
                ])
                for package in self.packages
            ]

        @classmethod
        def parse(cls, elem):
            return core.Result.parse(elem.find('result'))

    class GetPermissionDescriptor(core.operation_with_filter('GetPermissionDescriptor')):
        operator_name = 'reseller-plan'
        operation_name = 'get-permission-descriptor'
        min_api_version = '1.6.3.0'
        max_api_version = None

        @classmethod
        def parse(cls, command_node):
            """
            :type command_node: xml.etree.ElementTree.Element
            :rtype: parallels.plesk.utils.xml_rpc.plesk.core.Success|parallels.plesk.utils.xml_rpc.plesk.core.Failure
            """
            return core.Result.parse(command_node.find('result'), cls._parse_data)

        @classmethod
        def _parse_data(cls, result_node):
            """
            :type result_node: xml.etree.ElementTree.Element
            :rtype: parallels.plesk.utils.xml_rpc.plesk.core.Descriptor
            """
            return core.Descriptor.parse(result_node.find('descriptor'))

    class GetLimitDescriptor(core.operation_with_filter('GetLimitDescriptor')):
        operator_name = 'reseller-plan'
        operation_name = 'get-limit-descriptor'
        min_api_version = '1.6.3.0'
        max_api_version = None

        @classmethod
        def parse(cls, command_node):
            """
            :type command_node: xml.etree.ElementTree.Element
            :rtype: parallels.plesk.utils.xml_rpc.plesk.core.Success|parallels.plesk.utils.xml_rpc.plesk.core.Failure
            """
            return core.Result.parse(command_node.find('result'), cls._parse_data)

        @classmethod
        def _parse_data(cls, result_node):
            """
            :type result_node: xml.etree.ElementTree.Element
            :rtype: parallels.plesk.utils.xml_rpc.plesk.core.Descriptor
            """
            return core.Descriptor.parse(result_node.find('descriptor'))
