from collections import namedtuple

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

UserAddInfo = namedtuple('UserAddInfo', ('id', 'guid'))
UserContactInfo = namedtuple(
	'UserContactInfo', (
		'company', 'phone', 'fax', 'address', 'city', 'state', 'zip',
		'country', 'im', 'imtype', 'comment'))
UserGetInfo = namedtuple('UserGetInfo', ('gen_info', 'roles'))
UserGenInfo = namedtuple('UserGenInfo', ('login', 'name', 'owner_guid', 'status', 'guid', 'is_built_in', 'contact_info', 'external_id'))


class UserOperator(object):
	FilterAll = core.FilterAll
	FilterOwnerGuid = core.declare_filter('FilterOwnerGuid', 'owner-guid')

	class Dataset(object):
		GEN_INFO = 'gen-info'
		ROLES = 'roles'

		values = [GEN_INFO, ROLES]

	STATUS_DISABLED = 'disabled'
	STATUS_ENABLED = 'enabled'

	class Add(
			core.operation(
				'Add', (
					'login', 'passwd', 'owner_guid', 'name', 'roles',
					'contact_info', 'subscription_domain_id', 'status',
					'email'))):
		operator_name = 'user'
		operation_name = 'add'
		min_api_version = '1.6.4.0'
		max_api_version = None

		def inner_xml(self):
			return [
				elem('gen-info', seq(
					text_elem('login', self.login),
					text_elem('passwd', self.passwd),
					text_elem('owner-guid', self.owner_guid),
					text_elem('name', self.name),
					elem('contact-info', [
							text_elem(name, value) for name, value in self.contact_info._asdict().iteritems()
						]) if self.contact_info is not None else None,
					text_elem('status', self.status),
					text_elem('subscription-domain-id', self.subscription_domain_id),
					text_elem('email', self.email),
				)),
				elem('roles', [
					text_elem('name', role) for role in self.roles
				])
			]

		@classmethod
		def parse(cls, elem):
			assert(len(elem) == 1)
			return core.Result.parse(elem[0], cls._parse_data)

		@classmethod
		def _parse_data(cls, elem):
			id = int(elem.findtext('id'))
			return (id, UserAddInfo(
				id=id,
				guid=elem.findtext('guid')
			))

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

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

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

		@classmethod
		def _parse_data(cls, elem):
			gen_info = if_not_none(
				elem.find('data/gen-info'),
				lambda gen_info_node:
					UserGenInfo(
						login=gen_info_node.findtext('login'),
						name=gen_info_node.findtext('name'),
						owner_guid=gen_info_node.findtext('owner-guid'), 
						status=gen_info_node.findtext('status'),
						guid=gen_info_node.findtext('guid'),
						is_built_in=parse_bool(gen_info_node.findtext('is-built-in')),
						contact_info=if_not_none(
							gen_info_node.find('contact-info'), 
							lambda contact_node:
								UserContactInfo(
									company=contact_node.findtext('company'), 
									phone=contact_node.findtext('phone'), 
									fax=contact_node.findtext('fax'), 
									address=contact_node.findtext('address'), 
									city=contact_node.findtext('city'), 
									state=contact_node.findtext('state'), 
									zip=contact_node.findtext('zip'), 
									country=contact_node.findtext('country'),
									im=contact_node.findtext('im'),
									imtype=contact_node.findtext('imtype'),
									comment=contact_node.findtext('comment'),
								)
						), 
						external_id=gen_info_node.findtext('external-id'),
					)
			)

			roles = if_not_none(
				elem.find('data/roles'),
				lambda roles_node:
					[name_node.text for name_node in roles_node.findall('name')]
			)

			return UserGetInfo(gen_info, roles)