from collections import namedtuple

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

AddonPlanInfo = namedtuple('AddonPlanInfo', ('plan_id', 'guid', 'name'))

ServicePlanAddonLimits = namedtuple('ServicePlanLimits', (
    'overuse',
    'limits'  # list of ServicePlanAddonLimit
))
ServicePlanAddonLimit = namedtuple('ServicePlanAddonLimit', ('name', 'value',))
ServicePlanAddonPermission = namedtuple('ServicePlanAddonPermission', ('name', 'value',))
ServicePlanAddonHostingSetting = namedtuple('ServicePlanAddonHostingSetting', ('name', 'value',))
ServicePlanAddonPHPSetting = namedtuple('ServicePlanAddonPHPSetting', ('name', 'value',))
ServicePlanAddonApsPackage = namedtuple('ServicePlanApsPackage', (
    # str | unicode
    'name',
    # str | unicode
    'value',
))


class ServicePlanAddonOperator(object):
    FilterAll = core.FilterAll
    FilterById = core.declare_filter('FilterById', 'id')
    FilterByGuid = core.declare_filter('FilterByGuid', 'guid')

    class Get(core.operation_with_filter('Get', ('owner_id',))):
        operator_name = 'service-plan-addon'
        operation_name = 'get'
        min_api_version = '1.6.3.0'
        max_api_version = None

        def data_xml(self):
            return seq(
                text_elem('owner-id', self.owner_id),
            )

        @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'))
            guid = elem.findtext('guid')
            name = elem.findtext('name')
            return AddonPlanInfo(plan_id=plan_id, guid=guid, name=name)

    class Add(core.operation('Add', (
        'name', 'owner_login', 'limits', 'permissions', 'hosting', 'php_settings'
    ))):
        operator_name = 'service-plan-addon'
        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),
                text_elem('owner-login', self.owner_login),
                self._limits_xml(),
                self._hosting_xml(),
                self._permissions_xml(),
                self._php_settings_xml()
            )

        def _limits_xml(self):
            return elem('limits', seq(text_elem('overuse', self.limits.overuse)) + [
                elem('limit', [text_elem('name', limit.name), text_elem('value', limit.value)])
                for limit in self.limits.limits
            ])

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

        def _hosting_xml(self):
            if self.hosting is None:
                return None

            return elem('hosting', seq(*[
                elem('property', [text_elem('name', prop.name), text_elem('value', prop.value)])
                for prop in self.hosting
            ]))

        def _php_settings_xml(self):
            if self.php_settings is None:
                return None
            return elem(
                'php-settings', [
                    elem('setting', [text_elem('name', setting.name), text_elem('value', setting.value)])
                    for setting in self.php_settings
                ]
            )

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

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

        def data_xml(self):
            return seq(text_elem('owner-login', self.owner_login)) + [
                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'))
