var PbRelationAddress = Class.create({
	lastParentAddress: {},
	initialize: function (typeId, autoSyntaxOpts)
	{
		this.typeId = typeId;

		if ($('relation_address_inherit_from_' + this.typeId)) {
			$('relation_address_inherit_from_' + this.typeId)
				.observe('change', (function () {this.checkFields();}).bind(this));
		}

		this.checkFields(true);

		var k, elem, forceInitialAutoValue;
		if (autoSyntaxOpts.name) {
			elem = $('relation_address_' + this.typeId);
			if (elem) {
				elem = elem.select('.address-name');
				if (elem) {
					elem = elem.first();
					if (elem && !Object.isUndefined(autoSyntaxOpts.name['syntax'])) {
						if (Object.isUndefined(autoSyntaxOpts.name['defaultAuto'])) {
							forceInitialAutoValue = null;
						} else {
							forceInitialAutoValue = autoSyntaxOpts.name.defaultAuto;
						}
						this.initAutoSyntax(elem, autoSyntaxOpts.name.syntax, forceInitialAutoValue);
					}
				}
			}
		}

		if (autoSyntaxOpts.freetext) {
			elem = $('relation_address_' + this.typeId);
			if (elem) {
				elem = elem.select('.address-freetext');
				if (elem) {
					elem = elem.first();
					if (elem && !Object.isUndefined(autoSyntaxOpts.freetext['syntax'])) {
						if (Object.isUndefined(autoSyntaxOpts.freetext['defaultAuto'])) {
							forceInitialAutoValue = false;
							if ($('relation_address_inherit_from_' + this.typeId)) {
								if ($F('relation_address_inherit_from_' + this.typeId)) {
									forceInitialAutoValue = true;
								}
							}
						} else {
							forceInitialAutoValue = autoSyntaxOpts.freetext.defaultAuto;
						}
						this.initAutoSyntax(elem, autoSyntaxOpts.freetext.syntax, forceInitialAutoValue);
					}
				}
			}
		}
	},
	initAutoSyntax: function (elem, syntax, forceInitialAutoValue)
	{
		var fieldList = {};
		var tokens = $H();
		var tokenName, tokenField, processFunc, label;
		var allTokens = syntax.match(/((^|[^\[])%[a-z0-9]+|\[%[a-z0-9]+($|[^:]))/gi);
		if (allTokens) {
			var triggerFunc = (function (event) {
				var triggerElem = event.element();
				if (!Object.isUndefined(triggerElem['prevSyntaxValue-' + elem.id]) && triggerElem.value == triggerElem['prevSyntaxValue-' + elem.id]) {
					return true;
				}
				triggerElem['prevSyntaxValue-' + elem.id] = triggerElem.value + "";

				var newValue = this.applyTokens(syntax, tokens);

				if (elem.autoChange) {
					elem.previousSibling.value = newValue;
					elem.value = newValue;
				} else {
					if (elem.value != elem.autoValue) {
						elem.addClassName('unlinked-modified');
					} else {
						elem.removeClassName('unlinked-modified');
					}
				}
				elem.autoValue = newValue;
			}).bind(this);
			
			var processedTokens = {};
			for (var i = 0; i < allTokens.length; i++) {
				tokenName = allTokens[i].replace(/^.*?%(.*?):?$/, '$1');
				if (!Object.isUndefined(processedTokens[tokenName])) {
					continue;
				}
				processedTokens[tokenName] = true;
				processFunc = false;

				if (tokenName.match(/^\d+$/)) {
					tokenField = 'ff_' + tokenName;
				} else {
					switch (tokenName) {
						case 'F':
							tokenField = 'relation_firstname';
							break;
						case 'f':
							tokenField = 'relation_initials';
							break;
						case 'i':
							tokenField = 'relation_insertion';
							break;
						case 'n':
							tokenField = 'relation_name';
							break;
						default:
							tokenField = tokenName + "";
					}
				}

				tokenField = $(tokenField);
				if (tokenField) {
					if (!tokenField.tagName.match(/(input|select|textarea)/i)) {
						tokenField = tokenField.select('input, select, textarea').first();
					}
				} else {
					tokenField = '';
				}

				if (tokenField) {
					// Add name of this field to the fieldList
					label = tokenField.up('.field');
					if (label && (label = label.down('label'))) {
						label = label.innerHTML.stripTags().strip().replace(/\*\s*$/, '');
						fieldList[label] = label;
					}

					// processfunc for select elements
					if (tokenField.tagName.toLowerCase() === 'select') {
						processFunc = function (field) {							
							var selectedOption = field.select('option').find(function(e) {return e.selected == true;});
							return selectedOption ? selectedOption.innerHTML : '';
						}
					}
					
					// processfunc for radio groups
					if (tokenField.tagName.toLowerCase() == 'input' && tokenField.type == 'radio') {
						var allFields = $A(document.getElementsByName(tokenField.name));
						processFunc = function (field) {
							var value = '';
							allFields.each(function (field) {
								if (field.checked) {
									value = field.value;
								}
							});
							return value;
						};
						allFields.each(function (field) {
							field.observe('change', triggerFunc);
						});
					} else {
						tokenField.observe('change', triggerFunc);
						tokenField.observe('blur', triggerFunc);
					}
				} else {
					tokenField = '';
				}

				tokens.set(tokenName, {'field': tokenField, 'processFunc': processFunc});
			}
		}

		elem.autoValue	= this.applyTokens(syntax, tokens);
		if (forceInitialAutoValue == null || elem.value != "") {
			elem.autoChange	= (elem.value == elem.autoValue);
		} else {
			elem.autoChange = forceInitialAutoValue;
		}

		// Place toggle link in front of the input's label
		var linkIcon = PbLib.getNewURI('ui/uibase/icons/16/link.png');
		var unLinkIcon = PbLib.getNewURI('ui/uibase/icons/16/link_delete.png');
		var enableTitle = PbLib.g('Enable automatic value based on: #{fieldlist}')
			.interpolate({'fieldlist': Object.values(fieldList).join(', ')});
		var disableTitle = PbLib.g('Disable automatic value based on: #{fieldlist}')
			.interpolate({'fieldlist': Object.values(fieldList).join(', ')});
		var toggleLink = new Element('img', {
			'src': linkIcon,
			'title': enableTitle
			});
		var label = elem.previous('label');
		label.insertBefore(document.createTextNode(' '), label.firstChild);
		label.insertBefore(toggleLink, label.firstChild);
		toggleLink.observe('click', function () {
			if (elem.autoChange) {
				elem.parentNode.removeChild(elem.previousSibling);
				elem.show();

				elem.autoChange = false;
				toggleLink.src = linkIcon;
				toggleLink.title = enableTitle;

				if (elem.value != elem.autoValue) {
					elem.addClassName('unlinked-modified');
				} else {
					elem.removeClassName('unlinked-modified');
				}
			} else {
				var displayField = new Element('input', {
					'type': elem.type,
					'disabled': true,
					'class': elem.className,
					'value': elem.autoValue
					});
				elem.hide();
				elem.parentNode.insertBefore(displayField, elem);

				elem.autoChange = true;
				elem.value = elem.autoValue;
				toggleLink.src = unLinkIcon;
				toggleLink.title = disableTitle;
			}
		});

		elem.observe('change', function () {
			elem.removeClassName('unlinked-modified');
		});

		if (elem.autoChange) {
			var displayField = new Element('input', {
				'type': elem.type,
				'disabled': true,
				'class': elem.className,
				'value': elem.autoValue
				});
			elem.hide();
			elem.parentNode.insertBefore(displayField, elem);
			toggleLink.src = unLinkIcon;
		}
	},
	applyTokens: function (syntax, tokens)
	{
		var newValue = syntax + "";
		tokens.each(function (tokenPair) {
			var tokenValue = '';
			if (tokenPair.value.field) {
				tokenValue = $F(tokenPair.value.field);
				if (tokenPair.value.processFunc) {
					tokenValue = tokenPair.value.processFunc(tokenPair.value.field, tokenValue);
				}
			}

			if (tokenValue == '') {
				newValue = newValue.replace(new RegExp('\\[%' + tokenPair.key + ':([^\\[\\]]*)\\]', 'g'), '');
			} else {
				newValue = newValue.replace(new RegExp('\\[%' + tokenPair.key + ':([^\\[\\]]*)\\]', 'g'), '$1');
			}

			newValue = newValue.replace(new RegExp('%' + tokenPair.key, 'g'), tokenValue);
		});

		newValue = newValue.replace(/  +/, ' ').replace(/^\s*(\S([\s\S]*\S)?)?\s*$/, '$1');
		return newValue;
	},
	toggleDisabled: function (disabledVal)
	{
		var disabledVal = !!(disabledVal);
		['street', 'number', 'number_add', 'postcode', 'town', 'state', 'country'].each((function (partName)
		{
			var e = $('relation_address_' + this.typeId + '-' + partName);
			if (e) {
				e.disabled = disabledVal;
			}
		}).bind(this));
	},
	checkFields: function (firstCall)
	{
		var selectBox = $('relation_address_inherit_from_' + this.typeId);
		if (!selectBox) {
			return false;
		}
		var selectedRel = $F(selectBox);
		if (selectedRel) {
			this.toggleDisabled(false);

			var parentAddress = {};
			if (this.addressParents[this.typeId]) {
				if (this.addressParents[this.typeId]['full'][selectedRel]) {
					parentAddress = this.addressParents[this.typeId]['full'][selectedRel];
				}
			}

			var addressIsEmpty = true;
			$$('#relation_address_' + this.typeId + ' .address-field').each((function (field) {
				if ($F(field) != "") {
					if (!field.disabled && field.id != 'relation_address_' + this.typeId + '-country') {
						addressIsEmpty = false;
						throw $break;
					}
				}
			}).bind(this));

			['name', 'freetext', 'street', 'number', 'number_add', 'postcode', 'town', 'state', 'country'].each((function (partName)
			{
				var val = parentAddress[partName] ? parentAddress[partName] : '';
				if (partName == 'name') {
					var e = $('relation_address_' + this.typeId + '-name');
					if (!this.lastParentAddress[this.typeId]) {
						this.lastParentAddress[this.typeId] = {};
					}
					if (e && ((!this.lastParentAddress[this.typeId]['name'] && $F(e) != '') || (this.lastParentAddress[this.typeId]['name'] && $F(e) != this.lastParentAddress[this.typeId]['name']))) {
						return;
					}
				}
				if (partName == 'freetext') {
					val = val.split('\n');
					var fields = $('relation_address_' + this.typeId).select('.address-freetext');
					var s = fields.size();

					var curVal = [];
					for (var i = s - 1; i >= 0; i--) {
						var e = $('relation_address_' + this.typeId + '-freetext-' + i);
						if (e && e.value) {
							curVal.push(e.value);
						}
					}
					curVal = curVal.join('\n');
					if ((firstCall && !addressIsEmpty) || ((!this.lastParentAddress[this.typeId]['freetext'] && curVal != '') || (this.lastParentAddress[this.typeId]['freetext'] && curVal != this.lastParentAddress[this.typeId]['freetext']))) {
						return;
					}

					for (var i = s - 1; i >= 0; i--) {
						var tmpVal = val[s - i - 1] ? val[s - i - 1] : '';
						var e = $('relation_address_' + this.typeId + '-freetext-' + i);
						if (e) {
							e.value = tmpVal;
						}
					}
				} else {
					var e = $('relation_address_' + this.typeId + '-' + partName);
					if (e) {
						e.value = val;
					}
				}
			}).bind(this));

			$('relation_address_' + this.typeId + '-country').fire('pb:change');
			this.toggleDisabled(true);

			this.lastParentAddress[this.typeId] = parentAddress;
		} else {
			this.toggleDisabled(false);
		}
	}
});