var Helper = {
	
	setCheckClass: function(elName, newClass, accHeightReset) {
		var inputEl = $(elName);
		var flag = inputEl.getParent().getElement('span.statusFlag');
		
		// default is to reset accordion height
		if (accHeightReset == null) {
			accHeightReset = true;
		}
		
		if (flag == null) return;
		
		flag.removeClass('stateUnchecked');
		flag.removeClass('stateError');
		flag.removeClass('stateOK');
		switch (newClass) {
			case ('stateUnchecked'): {
				flag.addClass('stateUnchecked');
				break;
			}
			case ('stateError'): {
				flag.addClass('stateError');
				inputEl.addClass('error');
				break;
			}
			case ('stateOK'): {
				flag.addClass('stateOK');
				// fall through
			}
			case ('stateUnmarked'): {
				// fall through
			}
			default: {
				inputEl.removeClass('error');
				Helper.deleteErrorMessage(flag);
				if (accHeightReset) {
					Helper.resetAccordionHeight(flag);
				}
			}
		}
	},
	
	setErrorMessage: function(elName, msg, accHeightReset) {
		var el = $(elName);
		var errorElName = el.get('id') + "ErrorMessage";
		var errorEl = $(errorElName);
		
		// default is to assume accordion
		if (accHeightReset == null) {
			accHeightReset = true;
		}
		
		if ($defined(errorEl)) errorEl.destroy();
		var myElement = new Element('span');
		myElement.addClass('error');
		myElement.set('id', errorElName);
		myElement.set('html', msg);
		myElement.inject(el.getParent('li'), "top");
		if (accHeightReset) {
			Helper.resetAccordionHeight(el);
		}
	},
	
	deleteErrorMessage: function(el) {
		var errMsg = el.getParent('li').getElement('span.error');
		if ($defined(errMsg)) errMsg.destroy();
		el.removeClass('errorBox');
	},
	
	resetAccordionHeight: function(el, extra) {
		if (extra == null) {
			extra = 0;
		}
		var submitButton = $('input#changePasswordSubmit');
		if ($defined(submitButton)) var submitButtonHeight = submitButton.getSize().y;
		var newHeight = el.getParent('ol').getSize().y + submitButtonHeight + extra;
		
		el.getParent('div.toggledElementAlt').setStyle('height', newHeight);
	},
	
	toggleDeliveryAddressFields: function() {
		if (!Page.useBillingAddrChecked) {
			Page.useBillingAddrChecked = true;
			$each(['building', 'street', 'area', 'city', 'county', 'postcode', 'countryid', 'stateid'], function(val) {
				var fieldName = 'delivery' + val;
				var billingName = 'billing' + val;
				var field = $(fieldName);
				
				field.set('value', $(billingName).get('value'));
				if (fieldName != 'deliveryarea') {
					Helper.setCheckClass(fieldName, 'stateUnchecked');
					Helper.deleteErrorMessage(field);
				}
				field.set('disabled', 'disabled');
				
				field.fireEvent('change');
			});
			
			Helper.resetAccordionHeight($('deliverybuilding'));
		}
		else {
			Page.useBillingAddrChecked = false;
			$each(['building', 'street', 'area', 'city', 'county', 'postcode', 'countryid', 'stateid'], function(val) {
				$('delivery' + val).erase('disabled');
			});
		}
	}
	
}


/* Validates whether a required field has
 * some data in it when the user leaves it.
 */
var RequiredFieldValidator = new Class({
	Implements: [Options, Events],
	options: {
		'classStateUnchecked': 'stateUnchecked',
		'classStateOK':		'stateOK',
		'classStateError':	'stateError',
		'classStateUnmarked': 'stateUnmarked',
		'classUserDataPresent':	'userData',
		'classStatusFlag':	'statusFlag',
		'classErrorBox':	'errorBox',
		'classErrorMessage':'error',
		'errorOnEmpty':		true,
		'showStatusFlagOnEmpty': true,
		'showTextInBox':	false,
		'errorMessage':		"Some information is required",
		'parentElement': 'li'
		/*
		 onComplete: 	$empty,
		 onOK: 			$empty,
		 onError:		$empty,
		 onUnchecked:	$empty
		*/
	},
	initialize: function(el, defaultText, options) {
		this.setOptions(options);
		this.el = $(el);
		this.defaultText = defaultText;
		
		this.el.addEvent('focus', function() {
			if (this.el.get('value') == defaultText) {
				this.el.set('value', '');
			}
			this.setCheckClass(this.options.classStateUnchecked);
			this.el.addClass(this.options.classUserDataPresent);
		}.bind(this));
			
		this.el.addEvent('blur', function() {
			var value = this.el.get('value');
			if (value == "" || value == defaultText) {
				this.el.removeClass(this.options.classUserDataPresent);
				if (this.options.errorOnEmpty) {
					this.setCheckClass(this.options.classStateError);
					this.setErrorMessage(this.options.errorMessage);
					this.fireEvent('onError', [this.el, this.el.get('value')]);
				}
				else {
					if (this.options.showTextInBox) this.el.set('value', defaultText);
					if (this.options.showStatusFlagOnEmpty) {
						this.setCheckClass(this.options.classStateUnchecked);
					} else {
						this.setCheckClass(this.options.classStateUnmarked);
					}
					this.deleteErrorMessage();
					this.fireEvent('onUnchecked', [this.el, this.el.get('value')]);
				}
				this.fireEvent('onComplete', [this.el, this.el.get('value')]);
			}
			else {
				this.validate(value);
			}
		}.bind(this));
	},
	
	setCheckClass: function(newClass) {
		var flag = this.el.getParent(this.options.parentElement).getElement('.'+this.options.classStatusFlag);
		
		flag.removeClass(this.options.classStateUnchecked);
		flag.removeClass(this.options.classStateOK);
		flag.removeClass(this.options.classStateError);
		switch (newClass) {
			case ('stateUnchecked'): {
				if (!this.options.errorOnEmpty) this.el.removeClass(this.options.classErrorBox);
				flag.addClass(this.options.classStateUnchecked);
				break;
			}
			case ('stateError'): {
				this.el.addClass(this.options.classErrorBox);
				flag.addClass(this.options.classStateError);
				break;
			}
			case ('stateOK'): {
				flag.addClass(this.options.classStateOK);
				// fall through
			}
			case ('stateUnmarked'): {
				// fall through
			}
			default: {
				this.el.removeClass(this.options.classErrorBox);
				this.deleteErrorMessage();
			}
		}
	},

	setErrorMessage: function(msg) {
		var errorElName = this.el.get('id') + "ErrorMessage";
		var errorEl = $(errorElName);
		
		if ($defined(errorEl)) errorEl.destroy();
		var myElement = new Element('span');
		myElement.addClass(this.options.classErrorMessage);
		myElement.set('id', errorElName);
		myElement.set('html', msg);
		myElement.inject(this.el.getParent('li'), "top");
	},
	
	deleteErrorMessage: function() {
		var errMsg = $(this.el.get('id')+'ErrorMessage');
		if ($defined(errMsg)) errMsg.destroy();
	},
	
	validate: function(value) {
		this.setCheckClass('stateOK');
		this.fireEvent('onOK', [this.el, value]);
		this.fireEvent('onComplete', [this.el, value]);
	}
	
})

var RequiredFieldEmailValidator = new Class ({
	Extends: RequiredFieldValidator,
	options: {
		'errorMessageInvalidEmail': 'Please enter a valid email address'
	},
	
	initialize: function(el, defaultText, options) {
		this.parent(el, defaultText, options);
	},
	
	validate: function(value) {
		var req = new Request({
			method: 'post',
			url: "/ajaxfuncs.php",
			data: { 	'function' 	: 'isEmailValid',
						'value' 	: value },
			onComplete: function(response) {
				switch (response) {
					case ("0"): {
						// email format invalid
						this.setCheckClass('stateError');
						this.setErrorMessage(this.options.errorMessageInvalidEmail);
						this.fireEvent('onError', [this.el, value]);
						break;
					}
					case ("1"): {
						// passed validation
						this.setCheckClass('stateOK');
						this.fireEvent('onError', [this.el, value]);
						break;
					}
				}
				this.fireEvent('onComplete', [this.el, value]);
			}.bind(this)
		}).send();
	}
})

var RequiredFieldEmailSubscribedValidator = new Class ({
	Extends: RequiredFieldValidator,
	options: {
		'errorMessageAlreadyRegistered': 'This email is already subscribed',
		'errorMessageInvalidEmail': 'Please enter a valid email address'
	},
	
	initialize: function(el, defaultText, options) {
		this.parent(el, defaultText, options);
	},
	
	validate: function(value) {
		var req = new Request({
			method: 'post',
			url: "/ajaxfuncs.php",
			data: { 	'function' 	: 'testEmailAddress',
						'value' 	: value },
			onComplete: function(response) {
				switch (response) {
					case ("1"): {
						// email format invalid
						this.setCheckClass('stateError');
						this.setErrorMessage(this.options.errorMessageInvalidEmail);
						this.fireEvent('onError', [this.el, value]);
						break;
					}
					case ("2"): {
						// email already subscribed
						this.setCheckClass('stateError');
						this.setErrorMessage(this.options.errorMessageAlreadyRegistered);
						this.fireEvent('onError', [this.el, value]);
						break;
					}
					case ("3"): {
						// passed validation
						this.setCheckClass('stateOK');
						this.fireEvent('onOK', [this.el, value]);
						break;
					}
				}
				this.fireEvent('onComplete', [this.el, value]);
			}.bind(this)
		}).send();
	}
})


var RequiredFieldEmailRegisteredValidator = new Class ({
	Extends: RequiredFieldValidator,
	options: {
		'errorMessageAlreadyRegistered': 'This email is already registered',
		'errorMessageInvalidEmail': 'Please enter a valid email address'
	},
	
	initialize: function(el, defaultText, options) {
		this.parent(el, defaultText, options);
	},
	
	validate: function(value) {
		var req = new Request({
			method: 'post',
			url: "/ajaxfuncs.php",
			data: { 	'function' 	: 'testEmailAddressAndRegistered',
						'value' 	: value },
			onComplete: function(response) {
				switch (response) {
					case ("1"): {
						// email format invalid
						this.setCheckClass('stateError');
						this.setErrorMessage(this.options.errorMessageInvalidEmail);
						this.fireEvent('onError', [this.el, value]);
						break;
					}
					case ("2"): {
						// email already registered
						this.setCheckClass('stateError');
						this.setErrorMessage(this.options.errorMessageAlreadyRegistered);
						this.fireEvent('onError', [this.el, value]);
						break;
					}
					case ("3"): {
						// passed validation
						this.setCheckClass('stateOK');
						this.fireEvent('onOK', [this.el, value]);
						break;
					}
				}
				this.fireEvent('onComplete', [this.el, value]);
			}.bind(this)
		}).send();
	}
})

var RequiredFieldEmailUpdate = new Class ({
	Extends: RequiredFieldValidator,
	options: {
		'errorMessageAlreadyRegistered': 'This email is already registered',
		'errorMessageInvalidEmail': 'Please enter a valid email address'
	},
	
	initialize: function(el, originalEmail, defaultText, options) {
		this.originalEmail = originalEmail;
		this.parent(el, defaultText, options);
	},
	
	validate: function(value) {
		if (value == this.originalEmail) {
			this.setCheckClass('stateOK');
			this.fireEvent('onOK', [this.el, value]);
			this.fireEvent('onComplete', [this.el, value]);
		}
		else {
			var req = new Request({
				method: 'post',
				url: "/ajaxfuncs.php",
				data: { 	'function' 	: 'testEmailAddressAndRegistered',
							'value' 	: value },
				onComplete: function(response) {
					switch (response) {
						case ("1"): {
							// email format invalid
							this.setCheckClass('stateError');
							this.setErrorMessage(this.options.errorMessageInvalidEmail);
							this.fireEvent('onError', [this.el, value]);
							break;
						}
						case ("2"): {
							// email already registered
							this.setCheckClass('stateError');
							this.setErrorMessage(this.options.errorMessageAlreadyRegistered);
							this.fireEvent('onError', [this.el, value]);
							break;
						}
						case ("3"): {
							// passed validation
							this.setCheckClass('stateOK');
							this.fireEvent('onOK', [this.el, value]);
							break;
						}
					}
					this.fireEvent('onComplete', [this.el, value]);
				}.bind(this)
			}).send();
		}
	}
})

var RequiredFieldEmailMatchesAnother = new Class({
	Extends: RequiredFieldValidator,
	options: {
		'errorMessage': "Please ensure the email addresses you enter match"
	},
	
	initialize: function(el, el2, defaultText, options) {
		this.el2 = el2;
		this.parent(el, defaultText, options);
	},
	
	validate: function(value) {
		if (value != this.el2.get('value')) {
			this.setCheckClass('stateError');
			this.setErrorMessage(this.options.errorMessage);
			this.fireEvent('onError', [this.el, value]);
		}
		// otherwise OK
		else {
			this.setCheckClass('stateOK');
			this.fireEvent('onOK', [this.el, value]);
		}
		this.fireEvent('onComplete', [this.el, value]);
	}
})

var RequiredFieldTelephoneValidator = new Class({
	Extends: RequiredFieldValidator,
	options: {
		'errorMessage': 'Please enter a valid telephone number (eg 08707 444 110)'
	},
	
	validate: function(value) {
		var req = new Request({
			method: 'post',
			url: "/ajaxfuncs.php",
			data: { 	'function' 	: 'testTelephone',
						'value' 	: value },
			onComplete: function(response) {
				switch (response) {
					case ("0"): {
						// bad telelphone format
						this.setCheckClass('stateError');
						this.setErrorMessage(this.options.errorMessage);
						this.fireEvent('onError', [this.el, value]);
						break;
					}
					default : {
						this.setCheckClass('stateOK');
						this.fireEvent('onOK', [this.el, value]);
					}
				}
				this.fireEvent('onComplete', [this.el, value]);
			}.bind(this)
		}).send();
	}
})

var RequiredFieldPostcodeValidator = new Class({
	Extends: RequiredFieldValidator,
	options: {
		'errorMessage': 'Please enter a valid postcode'
	},
	
	validate: function(value) {
		var req = new Request({
			method: 'post',
			url: "/ajaxfuncs.php",
			data: { 	'function' 	: 'testPostcode',
						'value' 	: value },
			onComplete: function(response) {
				switch (response) {
					case ("0"): {
						// bad postcode format
						this.setCheckClass('stateError');
						this.setErrorMessage(this.options.errorMessage);
						this.fireEvent('onError', [this.el, value]);
						break;
					}
					default : {
						this.setCheckClass('stateOK');
						this.fireEvent('onOK', [this.el, value]);
					}
				}
				this.fireEvent('onComplete', [this.el, value]);
			}.bind(this)
		}).send();
	}
})

var FieldTicker = new Class({
	Implements: [Options, Events],
	options: {
		'classStateOK':		'stateOK',
		'classUserDataPresent':	'userData',
		'classStatusFlag':	'statusFlag',
		'showTextInBox':	false
		/*
		 onComplete:$empty,
		 onOK: 		$empty,
		 onEmpty:	$empty
		*/
	},
	initialize: function(el, defaultText, options) {
		this.setOptions(options);
		this.el = $(el);
		this.defaultText = defaultText;
		
		this.el.addEvent('focus', function() {
			if (this.el.get('value') == defaultText) {
				this.el.set('value', '');
			}
			this.el.addClass(this.options.classUserDataPresent);
		}.bind(this));
			
		this.el.addEvent('blur', function() {
			var value = this.el.get('value');
			if (value == "" || value == defaultText) {
				this.el.removeClass(this.options.classUserDataPresent);
				if (this.options.showTextInBox) this.el.set('value', defaultText);
				this.setCheckClass('stateUnmarked');
				this.fireEvent('onEmpty', [this.el, value]);
			}
			else {
				this.setCheckClass('stateOK');
				this.fireEvent('onOK', [this.el, value]);
			}
			this.fireEvent('onComplete', [this.el, value]);
		}.bind(this));
		
		this.el.addEvent('keyup', function() {
			var value = this.el.get('value');
			if (value > "" && value != defaultText)
				this.setCheckClass('stateOK');
			else
				this.setCheckClass('stateUnmarked');
		}.bind(this));
	},
	
	setCheckClass: function(newClass) {
		var flag = this.el.getParent('li').getElement('.'+this.options.classStatusFlag);
		
		flag.removeClass(this.options.classStateOK);
		switch (newClass) {
			case ('stateOK'): {
				flag.addClass(this.options.classStateOK);
				// fall through
			}
			case ('stateUnmarked'): {
				// fall through
			}
			default: {
			}
		}
	}
})


