/* ************************************************************************************* *\
 * The MIT License
 * 
 *  - Updated for usage with MooTools 1.2
 *  - Added language support
 *  - Added a few validation types
 *  - Copyright (c) 2008 Lennart Pilon - http://ljpilon.nl
 *
 * Copyright (c) 2007 Fabio Zendhi Nagao - http://zend.lojcomm.com.br
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
\* ************************************************************************************* */
/***************************************************
 * Amended by Jake Dean at Creative Spark, (c) 2009
 ***************************************************/

if (!String.stripHTML) {
	String.implement({
		stripHTML: function(){
			var text = this.replace(/<([a-z]+)[^>]*>([\s\S]*?)<\/\1>/gi, '');
			return text;
		}
	});
}


var fValidator = new Class({
	Implements: [Options, Events],
	options: {
		msgContainerTag: "span",
		msgClass: "message",

		labelErrorClass: "error",
		labelValidClass: "valid",

		styleNeutral: {"background-color": "transparent"},
		styleInvalid: {"background-color": "#fcc"},
		styleValid: {"background-color": "#cfc"},

		language: "en",
		languageConfig: {	
			en: {	required:	"Please enter :field_name",
					alpha:		"Please enter alphabetic characters only",
					alphanum:	"Please enter alphanumeric characters only",
					integer:	"Please enter a valid integer",
					real:		"Please enter a valid number",
					date:		"Please enter a valid date (mm/dd/yyyy)",
					dateISO8601:"Please enter a valid date (yyyy-mm-dd)",
					dateEU:		"Please enter a valid date (dd-mm-yyyy)",
					email:		"Please enter a valid email",
					phone:		"Please enter a valid phone number",
					url:		"Please enter a valid URL",
					zip:		"Please enter a valid postal code",
					postcode:	"Please enter a valid UK postcode",
					confirm:	"Confirm password does not match original password"
				}
		},

		required: {type: "required", re: /[^.*]/},
		alpha: {type: "alpha", re: /^[a-z ._-]+$/i},
		alphanum: {type: "alphanum", re: /^[a-z0-9 ._-]+$/i},
		integer: {type: "integer", re: /^[-+]?\d+$/},
		real: {type: "real", re: /^[-+]?\d*\.?\d+$/},
		date: {type: "date", re: /^((((0[13578])|([13578])|(1[02]))[\/](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\/](([1-9])|([0-2][0-9])|(30)))|((2|02)[\/](([1-9])|([0-2][0-9]))))[\/]\d{4}$|^\d{4}$/},
		dateISO8601: {type: "dateISO8601", re: /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/},
		dateEU: {type: "dateEU", re: /^(((([1-9])|([0-2][0-9])|(3[01]))[-]((0[13578])|([13578])|(1[02])))|((([1-9])|([0-2][0-9])|(30))[-]((0[469])|([469])|(11)))|((([1-9])|([0-2][0-9])))[-](2|02))[-]\d{4}$|^\d{4}$/},
		email: {type: "email", re: /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i},
		phone: {type: "phone", re: /^[\d\s ().+-]+$/},
		url: {type: "url", re: /^(http|https|ftp)\:\/\/[a-z0-9\-\.]+\.[a-z]{2,3}(:[a-z0-9]*)?\/?([a-z0-9\-\._\?\,\'\/\\\+&amp;%\$#\=~])*$/i},
		confirm: {type: "confirm"},
		zip: {type: "zip", re: /^\d{5}(-\d{4})?$/i},
		postcode: {type: "postcode", re: /^([A-PR-UWYZ0-9][A-HK-Y0-9][AEHMNPRTVXY0-9]?[ABEHMNPRVWXY0-9]? {1,2}[0-9][ABD-HJLN-UW-Z]{2}|GIR 0AA)$/i},

		onValid: Class.empty,
		onInvalid: Class.empty
	},

	initialize: function(form, options) {
		this.form = $(form);
		this.setOptions(options);

		this.fields = this.form.getElements("*[class^=validate]");
		this.validations = [];

		this.fields.each(function(element) {
			if(!this._isChildType(element)) element.setStyles(this.options.styleNeutral);
			element.cbErr = 0;
			var classes = element.getProperty("class").split(' ');
			classes.each(function(klass) {
				if(klass.match(/^validate-(.+)-$/)) {
					var aFilters = eval('['+klass.match(/^validate-(.+)-$/)[1]+']');
					for(var i = 0; i < aFilters.length; i++) {
						if(this.options[aFilters[i]]) this.register(element, this.options[aFilters[i]]);
						if(aFilters[i].charAt(0) == '=') this.register(element, $extend(this.options.confirm, {idField: aFilters[i].substr(1)}));
					}
				}
			}.bind(this));
		}.bind(this));

		this.form.addEvents({
			"submit": this._onSubmit.bind(this),
			"reset": this._onReset.bind(this)
		});
	},

	register: function(field, options) {
		field = $(field);
		this.validations.push([field, options]);
		field.addEvent("blur", function() {
			this._validate(field, options);
		}.bind(this));
	},

	_isChildType: function(el) {
		var elType = el.type.toLowerCase();
		if((elType == "radio") || (elType == "checkbox")) return true;
		return false;
	},

	_validate: function(field, options) {
		switch(options.type) {
			case "confirm":
				if($(options.idField).get('value') == field.get('value')) this._msgValid(field, options);
				else this._msgError(field, options);
				break;
			default:
				if(options.re.test(field.get('value'))) {
					this._msgValid(field, options);
				} else if (field.get('value') == '' && options.type != 'required') {
					this._msgClear(field, options);
				} else {
					this._msgError(field, options);
				}
		}
	},

	_validateChild: function(child, options) {
		var nlButtonGroup = this.form[child.getProperty("name")];
		var cbCheckeds = 0;
		var isValid = true;
 		for(var i = 0; i < nlButtonGroup.length; i++) {
			if(nlButtonGroup[i].checked) {
				cbCheckeds++;
				if(!options.re.test(nlButtonGroup[i].get('value'))) {
					isValid = false;
					break;
				}
			}
		}
		if(cbCheckeds == 0 && options.type == "required") isValid = false;
		if(isValid) this._msgValid(child, options);
		else this._msgError(child, options);
	},

	_msgError: function(owner, options) {
		this._msgDisplay(owner, options, false);
	},

	_msgValid: function(owner, options) {
		this._msgDisplay(owner, options, true);
	},

	_msgDisplay: function(owner, options, valid) {
		var showClass = (valid ? this.options.labelValidClass : this.options.labelErrorClass);
		var hideClass = (valid ? this.options.labelErrorClass : this.options.labelValidClass);

		var setmsg = function(){
			owner.getParent('label').removeClass(hideClass).addClass(showClass);

			var msg = this.options.languageConfig[this.options.language][options.type];
			msg = msg.replace(':field_name', owner.getPrevious('span').get('html').stripHTML().toLowerCase());

			var msgContainer = new Element(this.options.msgContainerTag, {
				"class": this.options.msgClass,
				'html': (valid ? '&nbsp;' : msg),
				'styles': {"opacity": 0}
			}).injectAfter(owner);

			msgContainer.tween('opacity', 1);

			if (valid) {
				owner.cbErr = 0;
			} else {
				owner.cbErr++;
			}
			this._chkStatus(owner, options);
		}.bind(this);

		var el = owner.getNext('span.' + this.options.msgClass);

		if (el) {
			if (!valid || !owner.getParent('label').hasClass(showClass)) {
				el.set('tween', {
					onComplete: function(){
						el.destroy();
						setmsg();
					}.bind(this)
				}).tween('opacity', 0);
			}
		} else {
			setmsg();
		}
	},

	_msgClear: function(owner, options) {
		var el = owner.getNext('span.' + this.options.msgClass);

		if (el) {
			el.set('tween', {
				onComplete: function(){
					el.destroy();
				}.bind(this)
			}).tween('opacity', 0);
		}
	},

	_chkStatus: function(field, options) {
		if(field.cbErr == 0) {
			field.tween(this.options.styleValid);
			this.fireEvent("onValid", [field, options], 50);
		} else {
			field.tween(this.options.styleInvalid);
			this.fireEvent("onInvalid", [field, options], 50);
		}
	},

	_onSubmit: function(event) {
		var event = new Event(event);
		var isValid = true;

		this.validations.each(function(array) {
			if(this._isChildType(array[0])) this._validateChild(array[0], array[1]);
			else this._validate(array[0], array[1]);
			if(array[0].cbErr > 0) isValid = false;
		}.bind(this));

		if(!isValid) event.stop();
		return isValid;
	},

	_onReset: function() {
		this.validations.each(function(array) {
			if(!this._isChildType(array[0])) array[0].setStyles(this.options.styleNeutral);
			array[0].cbErr = 0;
			this._msgRemove(array[0], array[1], true);
		}.bind(this));
	}
});


window.addEvent('domready', function(){
	$$('form.validate').each(function(el){
		new fValidator(el);
	});
});