# Copyright (c) 2014, 2015, 2016, 2017 Timothy Savannah under LGPL version 2.1. See LICENSE for more information.
#
# chain - Support for chaining multiple IRField's (so for example to compress a json value)
#


# vim:set ts=8 shiftwidth=8 softtabstop=8 noexpandtab :

from ..compat_str import to_unicode

from . import IRField, irNull

try:
	unicode
except NameError:
	unicode = str

class IRFieldChain(IRField):

	# TODO: We can probably index if all chained field types are indexable, but just disallow for now.
	CAN_INDEX = False

	def __init__(self, name, chainedFields, defaultValue=irNull):
		if not name:
			raise ValueError('IRFieldChain has empty name.')

		self.chainedFields = []

		for field in chainedFields:
			# If we got jsut a class, construct it.
			if type(field) == type:
				field = field()
			if str(field) != '':
				raise ValueError('IRFieldChain has chained fields with a name set. The name should only be provided to the IRFieldChain object itself.')
			if not issubclass(field.__class__, IRField):
				raise ValueError("IRFieldChain's 'chainedFields' (second arg) should only contain IRField objects or subclasses thereof. Got: %s %s" %(str(type(field)), repr(field)))


			self.chainedFields.append(field)

		self.defaultValue = defaultValue



	def _toStorage(self, value):
		'''
			_toStorage - Convert the value to a string representation for storage.

			@param value - The value of the item to convert
			@return A string value suitable for storing.
		'''

		for chainedField in self.chainedFields:
			value = chainedField.toStorage(value)

		return value

	def _fromStorage(self, value):
		'''
			_fromStorage - Convert the value from storage (string) to the value type.

			@return - The converted value, or "irNull" if no value was defined (and field type is not default/string)
		'''

		for i in range(len(self.chainedFields)-1, -1, -1):
			chainedField = self.chainedFields[i]
			value = chainedField._fromStorage(value)

		return value
	
	def _fromInput(self, value):

		for i in range(len(self.chainedFields)-1, -1, -1):
			chainedField = self.chainedFields[i]
			value = chainedField._fromInput(value)

		return value

	def _getReprProperties(self):
		chainedFieldsRepr = []
		for chainedField in self.chainedFields:
			fieldRepr = chainedField.__class__.__name__ + '( ' + ', '.join(chainedField._getReprProperties()) + ' )'
			chainedFieldsRepr.append(fieldRepr)

		return ['chainedFields=[ %s ]' %(', '.join(chainedFieldsRepr), )]

	def copy(self):
		return self.__class__(name=self.name, chainedFields=[field.copy() for field in self.chainedFields], defaultValue=self.defaultValue)


	def __new__(self, name, chainedFields=None, defaultValue=irNull):
		if not name:
			raise ValueError('IRChainedField defined without a name!')

		return IRField.__new__(self, name)


# vim:set ts=8 shiftwidth=8 softtabstop=8 noexpandtab :

@@ -411,191 +411,742 @@
 d):%0A
-%0A%09# TODO: We can probably index if all chained field types are indexable, but just disallow for now.%0A%09CAN_INDEX = False%0A%0A%09def __init__(self, name, chainedFields, defaultValue=irNull):
+%09'''%0A%09   IRFieldChain -%0A%09   %0A%09   These chain together the operations from multiple fields.%0A%0A%09   toStorage is applied left-to-right,%0A%09   fromInput and fromStorage is applied right-to-left.%0A%0A%09   The output of one field is the input of the next.%0A%09'''%0A%0A%09# TODO: We can probably index if all chained field types are indexable, but just disallow for now.%0A%09CAN_INDEX = False%0A%0A%09def __init__(self, name, chainedFields, defaultValue=irNull):%0A%09%09'''%0A%09%09%09__init__ - Create an IRFieldChain object.%0A%0A%09%09%09  These chain together the operations from multiple fields.%0A%0A%09%09%09  toStorage is applied left-to-right,%0A%09%09%09  fromInput and fromStorage is applied right-to-left.%0A%0A%09%09%09  The output of one field is the input of the next.%0A%0A%0A%09%09%09@see IRField.__init__%0A%09%09'''
 %0A%09%09i

Add docstring to IRFieldChain