from collections import namedtuple

from parallels.core.utils.common import obj
from parallels.core.utils.common import sort_list_by_another
from parallels.core.utils.common.xml import elem, text_elem, seq
from parallels.core.utils.entity import Entity

from .. import core

CustomerInfo = namedtuple('CustomerInfo', ('id', 'owner_id', 'login', 'guid', 'pname', 'email'))
CustomerAddInfo = namedtuple('CustomerAddInfo', ('gen_info',))


class CustomerAddGenInfo(Entity):
    def __init__(
        self, pname, login, passwd, email, owner_id, address, city, country,
        pcode, phone, fax, cname, state, locale, description=None
    ):
        self._pname = pname
        self._login = login
        self._passwd = passwd
        self._email = email
        self._owner_id = owner_id
        self._address = address
        self._city = city
        self._country = country
        self._pcode = pcode
        self._phone = phone
        self._fax = fax
        self._cname = cname
        self._state = state
        self._locale = locale
        self._description = description

    @property
    def pname(self):
        return self._pname

    @property
    def login(self):
        return self._login

    @property
    def passwd(self):
        return self._passwd

    @property
    def email(self):
        return self._email

    @property
    def owner_id(self):
        return self._owner_id

    @property
    def address(self):
        return self._address

    @property
    def city(self):
        return self._city

    @property
    def country(self):
        return self._country

    @property
    def pcode(self):
        return self._pcode

    @property
    def phone(self):
        return self._phone

    @property
    def fax(self):
        return self._fax

    @property
    def cname(self):
        return self._cname

    @property
    def state(self):
        return self._state

    @property
    def locale(self):
        return self._locale

    @property
    def description(self):
        return self._description


CustomerSetInfo = namedtuple('CustomerSetInfo', (
    'status',  # value from CustomerStatus
    'locale',
))
CustomerAddResult = namedtuple('CustomerAddResult', ('customer_id', 'guid'))

CustomerStatus = obj(
    DISABLED_BY_ADMIN=16,
)


class CustomerOperator(object):
    ERR_CLIENT_DOES_NOT_EXIST = 1013

    FilterAll = core.FilterAll
    FilterByLogin = core.declare_filter('FilterByLogin', 'login')
    FilterById = core.declare_filter('FilterByLogin', 'id')

    class Dataset(object):
        GEN_INFO = 'gen_info'

        values = [GEN_INFO]

    class Get(core.operation_with_filter('Get', ('dataset',))):
        operator_name = 'customer'
        operation_name = 'get'
        min_api_version = '1.6.4.0'
        max_api_version = None

        def data_xml(self):
            return seq(
                elem('dataset', [elem(i) for i in sort_list_by_another(self.dataset, CustomerOperator.Dataset.values)])
            )

        @classmethod
        def parse(cls, elem):
            return core.parse_result_set(elem, cls._parse_data, 'id')

        @classmethod
        def _parse_data(cls, elem):
            id = int(elem.findtext('id'))
            return (id, CustomerInfo(
                id=id,
                login=elem.findtext('data/gen_info/login'),
                guid=elem.findtext('data/gen_info/guid'),
                pname=elem.findtext('data/gen_info/pname'),
                email=elem.findtext('data/gen_info/email'),
                owner_id=elem.findtext('data/gen_info/owner-id')
            ))

    class Add(core.operation('Add', 'customer_add_info')):
        operator_name = 'customer'
        operation_name = 'add'
        min_api_version = '1.6.4.0'
        max_api_version = None

        def inner_xml(self):
            return seq(
                elem('gen_info', seq(
                    text_elem('cname', self.customer_add_info.gen_info.cname),
                    text_elem('pname', self.customer_add_info.gen_info.pname),
                    text_elem('login', self.customer_add_info.gen_info.login),
                    text_elem('passwd', self.customer_add_info.gen_info.passwd),
                    text_elem('phone', self.customer_add_info.gen_info.phone),
                    text_elem('fax', self.customer_add_info.gen_info.fax),
                    text_elem('email', self.customer_add_info.gen_info.email),
                    text_elem('address', self.customer_add_info.gen_info.address),
                    text_elem('city', self.customer_add_info.gen_info.city),
                    text_elem('state', self.customer_add_info.gen_info.state),
                    text_elem('pcode', self.customer_add_info.gen_info.pcode),
                    text_elem('country', self.customer_add_info.gen_info.country),
                    text_elem('locale', self.customer_add_info.gen_info.locale),
                    text_elem('owner-id', self.customer_add_info.gen_info.owner_id),
                    text_elem('description', self.customer_add_info.gen_info.description),
                ))
            )

        @classmethod
        def parse(cls, elem):
            return core.Result.parse(elem.find('result'), cls._parse_data)
        
        @classmethod
        def _parse_data(cls, elem):
            return CustomerAddResult(
                customer_id=elem.findtext('id'),
                guid=elem.findtext('guid')
            )

    class Set(core.operation_with_filter('Set', ('customer_set_info',))):
        operator_name = 'customer'
        operation_name = 'set'
        min_api_version = '1.6.4.0'
        max_api_version = None

        def data_xml(self):
            return seq(
                elem('values', [elem('gen_info', seq(
                    text_elem('status', self.customer_set_info.status),
                    text_elem('locale', self.customer_set_info.locale),
                ))])
            )

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