/*globals $, $$, Element */
// set this variable to the function that handles an individual rule not being satisfied
// signature of the function must be func(el, message)
// by default, this does nothing

function handleInputError(el, msg) {}
var handleError = handleInputError;

function defaultErrorHandler() {
	if (this.el) {
		alert(this.options.message);
	}
}

function validateInput (el) {
	var optionIndex = (arguments.length > 1) ? 1 : 0;
	this.options = {
		type:				"string",
		required:			false,
		match:				null,
		regexp:				null,
		check:				null,
		maximum:			1e9,
		minimum:			-1e9,
		message:			"Value is invalid",
		defaultVal:			null,
		onSuccess:			null,
		onFailure:			defaultErrorHandler.bind(this),
		doOnBlur:			true
    };
	Object.extend(this.options,arguments[optionIndex] || {});
	
	var valid = true;
	if (!el.blurred || this.options.doOnBlur) {
		if (this.options.name === "") { this.options.name = el.name; }
		this.el = $$(el);
		var val = el.scan();
		if (this.options.required) {
			// Check that the input is non-empty
			if (el.type.toLowerCase() == 'checkbox') {
				if (!el.isChecked()) {
					valid = false;
					handleInputError(el, this.options.name + " must be checked");
				}
			} else if (val === "") {
				valid = false;
				handleInputError(el, this.options.name + " is required");
			}
		}
		if (this.options.match !== null) {
			if (val != this.options.match.value) {
				valid = false;
				handleInputError(el, this.options.name + " does not agree");
			}
		}
		if (this.options.regexp !== null && this.options.regexp.test) {
			if (!this.options.regexp.test(val)) {
				valid = false;
				handleInputError(el, this.options.name + " does not match regular expression");
			}
		}
		if (this.options.check !== null && typeof(this.options.check) === "function") {
			if (!this.options.check()) {
				valid = false;
				handleInputError(el, this.options.name + " does not pass advanced checking");
			}
		}
		if (val !== "") {
			if (this.options.type != "string") {
				if (this.options.type == "int" || this.options.type == "year" || this.options.type == "birthday") {
					var intval = parseInt(val, 10);
					if ((val !== "") && (isNaN(intval) || (intval != val))) {
						valid = false;
						handleInputError(el, this.options.name + " must be an integer");
					}
					ival = parseInt(val, 10);
					if (val !== "" && (this.options.type == "year" || this.options.type == "birthday") && ival < 100) {
						// handle y2k issues
						var date = new Date(),
							threshhold = this.options.type == "year" ? 50 : date.getYear() - 100,
							century = Math.floor(date.getFullYear()/100)*100;
						if (ival < threshhold) { ival += century; }
						else { ival += (century - 100); }
						el.update(ival);
					}
				}
				if (this.options.type == "float") {
					var floatval = parseFloat(val);
					if ((val !== "") && (isNaN(floatval) || (floatval != val)) ) {
						valid = false;
						handleInputError(el, this.options.name + " must be a float");
					}
				}
				if (this.options.type == "alpha") {
					if ((val !== "") && !val.match(/^[a-zA-Z]+$/)) {
						valid = false;
						handleInputError(el, this.options.name + " must be letters only");
					}
				}
				if (this.options.type == "alphanum") {
					if ((val !== "") && !val.match(/^[a-zA-Z0-9]+$/)) {
						valid = false;
						handleInputError(el, this.options.name + " must be alpha-numeric");
					}
				}
				if (this.options.type == "email") {
					if ((val !== "") && ! Constants.regexpEmail().test(val)) {
						valid = false;
						handleInputError(el, this.options.name + " must be a valid email address");
					}
				}
				if (this.options.type == "date") {
					var dateOk = false;
					if (val === "")
						{ dateOk = true; }
					else if (val.match(/^\d{1,2}[\.\/\-]\d{1,2}[\.\/\-](\d\d){1,2}$/))
						{ dateOk = true; }
					else if (val.match(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\. \d{1,2}, (\d\d){1,2}$/i))
						{ dateOk = true; }
					else if (val.match(/^((jan|febr)uary|march|april|may|ju(ne|ly)|august|(sept|nov|dec)ember|october) \d{1,2}, (\d\d){1,2}$/i))
						{ dateOk = true; }
					if (!dateOk) {
						valid = false;
						handleInputError(el, this.options.name + " must be a date");
					}
				}
				if (this.options.type == "time") {
					if ((val !== "") && !val.match(/^\d{1,2}(:\d{2}){1,2}( [apAP][mM])?$/)) {
						valid = false;
						handleInputError(el, this.options.name + " must be a time");
					}
				}
				if (this.options.type == "datetime") {
					var datetimeOk = false;
					if (val === "")
						{ datetimeOk = true; }
					else if (val.match(/^\d{1,2}[\.\/\-]\d{1,2}[\.\/\-](\d\d){1,2}([ \-]+\d{1,2}(:\d{2}){1,2}( [apAP][mM])?)?$/))
						{ datetimeOk = true; }
					else if (val.match(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\. \d{1,2}, (\d\d){1,2}([ \-]+\d{1,2}(:\d{2}){1,2}( [ap]m)?)?$/i))
						{ datetimeOk = true; }
					else if (val.match(/^((jan|febr)uary|march|april|may|ju(ne|ly)|august|(sept|nov|dec)ember|october) \d{1,2}, (\d\d){1,2}([ \-]+\d{1,2}(:\d{2}){1,2}( [ap]m)?)?$/i))
						{ datetimeOk = true; }
					if (!datetimeOk) {
						valid = false;
						handleInputError(el, this.options.name + " must be a date and time");
					}
				}
				if (this.options.type == "currency") {
					if ((val !== "") && !val.match(/^[$£]?[\d][\d\.\,]*$/)) {
						valid = false;
						handleInputError(el, this.options.name + " must be currency");
					}
				}
				if (this.options.type == "password") {
					// 6 or more characters, must contain 1+ letters AND 1+ numbers (alpha-num only)
					if ((val !== "") && (!val.match(/^[a-z0-9]{6,}$/i) || !val.match(/[0-9]/)  || !val.match(/[a-z]/i))) {
						valid = false;
						handleInputError(el, this.options.name + " must be at least 6 characters and can be only letters and numbers");
					}
				}
				if (valid && (this.options.type == "int" || this.options.type == "float" || this.options.type == "year")) {
					if (val > this.options.maximum) {
						valid = false;
						handleInputError(el, this.options.name + " must be below" + this.options.maximum);
					}
					if (val < this.options.minimum) {
						valid = false;
						handleInputError(el, this.options.name + " must be above" + this.options.minimum);
					}
				}
			}
		}
		if (!valid && this.options.defaultVal !== null) { el.value = this.options.defaultVal; }
		if (valid && this.options.onSuccess) { this.options.onSuccess(); }
		else if (!valid) { this.options.onFailure(); }
	}
	// clear out the flag telling us this validation was because of the blur event
	if (el.blurred) { el.blurred = false; }
	return valid;
}

Object.extend(Element,{
	addValidation: function () {
		var el = this,
			args = (arguments.length > 0) ? arguments[0] : null;
		el.validateFunc = function () { return validateInput(el, args); };
		if (el.form) {
			if (!el.form.validatable) { el.form.validatable = []; }
			el.form.validatable.push(el);
		}
		el.addEvent('blur', function () { el.blurred = true; return el.validateFunc(); } );
	}
});