
from collections import namedtuple


class ExpandError(Exception):
	def __init__(self, code, message):
		super(ExpandError, self).__init__(u"Expand error [%d]: %s" % (code, message))
		self.code = code
		self.message = message


class ExpandSystemError(Exception):
	def __init__(self, code, message):
		super(ExpandSystemError, self).__init__(u"Expand system error: [%d] %s" % (code, message))

		self.error_code = code
		self.error_message = message


class Result(object):
	@staticmethod
	def parse(elem, parse_data = lambda e: None):
		status = elem.findtext('status')
		if status == 'ok':
			return Success(parse_data(elem))
		else:
			code = int(elem.findtext('errcode'))
			message = elem.findtext('errtext')
			return Failure(code, message)


class Success(namedtuple('Success', ('data',))):
	@property
	def ok(self): return True

	def check(self): pass


class Failure(namedtuple('Failure', ('code', 'message'))):
	@property
	def ok(self): return False

	def check(self):
		raise ExpandError(self.code, self.message)
	
	@property
	def data(self):
		self.check()


def parse_result_set(elem, parse_data_function):
	if elem.findtext('system/status') == 'error':
		# handle system error, for example absence of license: return list of a single "Failure" object
		return [Result.parse(elem.find('system'))]
	else:
		return [Result.parse(r, parse_data_function) for r in elem.findall('result')]