from collections import namedtuple

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

DbServerInfo = namedtuple('DbServerInfo', ('id', 'host', 'port', 'dbtype', 'admin', 'password', 'status', 'db_num', 'default', 'local'))


class DbServerOperator(object):
	FilterAll = core.FilterAll
	FilterById = core.declare_filter('FilterById', 'id')

	class Get(core.operation_with_filter('Get')):
		operator_name = 'db_server'
		operation_name = 'get'
		min_api_version = '1.3.5.1'
		max_api_version = None

		@classmethod
		def parse(cls, elem):
			results = [core.Result.parse(r, cls._parse_data) for r in elem.findall('result')]
			if len(results) == 1 and results[0].ok and results[0].data is None:
				results = []
			return results
		
		@classmethod
		def _parse_data(cls, elem):
			db_server_id = if_not_none(elem.findtext('id'), int)
			if db_server_id is None:
				return None
			data_node = elem.find('data')
			return DbServerInfo(
				id=db_server_id,
				host=data_node.findtext('host'),
				port=if_not_none(data_node.findtext('port'), int),
				dbtype=data_node.findtext('type'),
				admin=data_node.findtext('admin'),
				password=data_node.findtext('password'),
				status=data_node.findtext('status'),
				db_num=int(data_node.findtext('db_num')),
				default=data_node.find('default') is not None,
				local=data_node.find('local') is not None,
			)

	class Add(core.operation('Add', ('host', 'port', 'db_type', 'admin', 'password', 'default'))):
		operator_name = 'db_server'
		operation_name = 'add'
		min_api_version = '1.3.5.1'
		max_api_version = None

		def inner_xml(self):
			return seq(
				text_elem('host', self.host),
				text_elem('port', self.port),
				text_elem('type', self.db_type),
				text_elem('admin', self.admin),
				text_elem('password', self.password),
				elem('default') if self.default else None,
			)
			
		@classmethod
		def parse(cls, elem):
			return core.Result.parse(elem.find('result'), cls._parse_data)
		
		@classmethod
		def _parse_data(cls, elem):
			return int(elem.findtext('id'))

	class RemoteDbRef(namedtuple('RemoteDbRef', ('id',))):
		def inner_xml(self):
			return [text_elem('id', self.id)]

	class LocalDbRef(namedtuple('LocalDbRef', ('dbtype',))):
		def inner_xml(self):
			return [text_elem('type', self.dbtype)]

	class SetDefault(core.operation('SetDefault', ('db_ref',))):
		operator_name = 'db_server'
		operation_name = 'set-default'
		min_api_version = '1.6.4.0'
		max_api_version = None

		def inner_xml(self):
			return self.db_ref.inner_xml()

		@classmethod
		def parse(cls, elem):
			return core.Result.parse(elem.find('result'), cls._parse_data)
		
		@classmethod
		def _parse_data(cls, elem):
			return if_not_none(elem.findtext('id'), int)