var DocumentUtil = (function() {
	var onReadyFunctions = [],
		ready = false,
		onReadyTimer;
	return {
		getQueryParamater:function(name, href) {
			var regex, results;

			if (self) {
				href = href || self.location.href;
			} else {
				href = href || top.location.href;
			}

			name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");

			regex = new RegExp("[\\?&]"+name+"=([^&#]*)");
			results = regex.exec(href);

			if(results) {
				return decodeURIComponent(results[1]);
			} else {
				return '';
			}
		},
		onReady:function(callback, scope) {
			onReadyFunctions.push({
				callback:callback,
				scope:scope || window
			});

			if (!onReadyTimer) {
				var fireDOMReady = function() {
					if(!ready) {
						ready = true;

						for (var i = 0; i < onReadyFunctions.length; i++) {
							var functionInfo = onReadyFunctions[i];
							functionInfo.callback.call(functionInfo.scope);
						}

						this.onReadyFunctions = [];

						if(document.removeEventListener) {
							document.removeEventListener("DOMContentLoaded", onChange, false);
						}

						document.onreadystatechange = null;
						window.onload = null;
						clearInterval(onReadyTimer);
						onReadyTimer = null;
					}
				};

				var onChange = function(e) {
					if(e && e.type == "DOMContentLoaded") {
						fireDOMReady.call(this);
					} else if(e && e.type == "load") {
						fireDOMReady.call(this);
					} else if(document.readyState) {
						if((/loaded|complete/).test(document.readyState)) {
							fireDOMReady.call(this);
						} else if(!!document.documentElement.doScroll) {
							try {
								this.ready || document.documentElement.doScroll('left');
							} catch(e) {
								return;
							}
							fireDOMReady.call(this);
						}
					}
				};

				var onChangeWrapper = function (e) {
					onChange.call(DocumentUtil, e);
				}

				if(document.addEventListener) {
					document.addEventListener("DOMContentLoaded", onChangeWrapper, false);
				}

				document.onreadystatechange = onChangeWrapper;
				this.onReadyTimer = setInterval(onChangeWrapper, 5);
				window.onload = onChangeWrapper;
			}
		}
	};
})();

var ArrayUtil = (function() {
	return {
		remove:function(cfg) {
			var rest = cfg.array.slice((cfg.to || cfg.from) + 1 || cfg.array.length);
			cfg.array.length = cfg.from < 0 ? cfg.array.length + cfg.from : cfg.from;
			return cfg.array.push.apply(cfg.array, rest);
		},
		contains:function(cfg) {
			for(var i = 0; i < cfg.array.length; i++) {
				if (cfg.array[i] === cfg.value) {
					return true;
				}
			}
			return false;
		}
	};
})();

var StringUtil = (function() {
	return {
		getNumbers:function(value) {
			var newValue = '';

			for (var i = 0 ; i < value.length ; i++) {
				var c = value.charAt(i);

				if (!isNaN(c) && c != ' ') {
					newValue += c;
				}
			}

			return newValue;
		},
		trim:function(value) {
			return value.replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, "");
		},
		startsWith:function(value, search) {
			return (value.match("^" + search) == search);
		},
		endsWith:function(value, search) {
			return (value.match(search + "$") == search);
		},
		contains:function(value, search) {
			return (value.match(search) == search);
		}
	};
})();

var ElementUtil = (function() {
	return {
		addEvent:function(cfg) {
			if (!cfg.elem || !cfg.event || !cfg.callback || typeof(cfg.callback) != 'function') {
				return false;
			}

			if (typeof(cfg.elem) == "string") {
				cfg.elem = document.getElementById(cfg.elem);
			}

			if (cfg.elem.addEventListener){
				cfg.elem.addEventListener(cfg.event, cfg.callback, false);
				return true;
			} else if (cfg.elem.attachEvent){
				var r = cfg.elem.attachEvent("on"+cfg.event, function() {
					cfg.callback.call(cfg.elem);
					});
				return r;
			} else {
				return false;
			}
		}
	};
})();

var FormUtil = (function() {
	var Validator = (function() {
		var namedInputs = {};
		var multiInputs = [
			'radiogroup',
			'checkgroup'
		];

		var isValidEmail = function(value) {
			return value.match(/^([\w-\.]+)@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|\d{1,3})(\]?)$/);
		};

		var isValidSimplePhoneNumber = function(value) {
			var start = "";

			if (StringUtil.startsWith(value, "1") && value.length == 11) {
				start = "1";
				value = value.substr(1);
			}

			var invalidNumbers = [
				"5555555555",
				"1234567890",
				"0123456789",
				"1234567890",
				"0987654321",
				"9876543210",
				"0000000000",
				"1111111111",
				"2222222222",
				"3333333333",
				"4444444444",
				"5555555555",
				"6666666666",
				"7777777777",
				"8888888888",
				"9999999999",
				"1222222222"
			];

			if (ArrayUtil.contains({array:invalidNumbers, value:value})) {
				return false;
			} else if (StringUtil.startsWith(value, "123") || StringUtil.startsWith(value, "1")) {
				return false;
			} else if (value.match(/\d{3}555\d{4}$/)) {
				return false;
			}

			return true;
		}

		var isValidPhoneNumber = function(value) {
			if (!(value.match(/^[0-9]{10}$/) || value.match(/^1[0-9]{10}$/))) {
				return false;
			}

			return isValidSimplePhoneNumber(value);
		};

		var isValidInternationalPhoneNumber = function(value) {
			if (!value.match(/^[0-9]{10,}$/)) {
				return false;
			}

			return isValidSimplePhoneNumber(value);
		};

		var isValidPostalCode = function(value) {
			var invalidNumbers = [
				"00000",
				"000000000"
			];

			if(!value.match(/^[0-9]{5}$/) && !value.match(/^[0-9]{9}$/)) {
				return false;
			} else if (ArrayUtil.contains({array:invalidNumbers, value:value})) {
				return false;
			}

			return true;
		};

		var isInputValid = function(cfg) {
			if (!ArrayUtil.contains({array:multiInputs, value:cfg.type.toLowerCase()})) {
				var input = document.getElementsByName(cfg.name)[0];

				input.value = StringUtil.trim(input.value);
				if (cfg.required) {
					if (input.value == '') {
						return false;
					}
				}

				if (input.value == '') {
					return true;
				}

				switch (cfg.type.toLowerCase()) {
					case 'phone':
						input.value = StringUtil.getNumbers(input.value);

						if (isValidPhoneNumber(input.value)) {
							if (input.value.length == 10) {
								input.value = '(' + input.value.toString().slice(0, 3) + ') ' + input.value.toString().slice(3, 6) + '-' + input.value.toString().slice(6, 10);
							} else if (input.value.length == 11) {
								input.value = input.value.toString().slice(0, 1) + ' (' + input.value.toString().slice(1, 4) + ') ' + input.value.toString().slice(4, 7) + '-' + input.value.toString().slice(7, 11);
							}
						} else {
							return false;
						}
						break;
					case 'email':
						if (!isValidEmail(input.value)) {
							return false;
						}
						break;
					case "postalcode":
						input.value = StringUtil.getNumbers(input.value);

						if (isValidPostalCode(input.value)) {
							if (input.value.length == 9) {
								input.value = input.value.toString().slice(0, 5) + '-' + input.value.toString().slice(5, 9);
							}
						} else {
							return false;
						}
						break;
					default:
						break;
				}

				for (var v in cfg.vars) {
					switch(v) {
						case 'minLength':
							if (input.value.length < cfg.vars[v]) {
								return false;
							}
							break;
						case 'maxLength':
							if (input.value.length > cfg.vars[v]) {
								return false;
							}
							break;
						default:
							break;
					}
				}
			} else {
				var inputs = document.getElementsByName(cfg.name);

				for (var i = 0 ; i < inputs.length ; i++) {
					switch (cfg.type.toLowerCase()) {
						case 'radiogroup':
						case 'checkgroup':
							if (inputs[i].checked) {
								return true;
							}
							break;
						default:
							break;
					}
				}

				return false;
			}

			return true;
		};

		return {
			setupOnBlur:function(cfg) {
				if (typeof(cfg.form) == 'string') {
					cfg.form = document.getElementById(cfg.form);
				}

				for (var i = 0 ; i < cfg.inputs.length ; i++) {
					var elems = document.getElementsByName(cfg.inputs[i].name);

					namedInputs[cfg.inputs[i].name] = cfg.inputs[i];

					for (var j = 0 ; j < elems.length ; j++) {
						ElementUtil.addEvent({elem:elems[j], event:'blur', callback:function() {
							var elems = document.getElementsByName(this.name);
							var valid = isInputValid(namedInputs[this.name]);

							for (var i = 0 ; i < elems.length ; i++) {
								if (valid) {
									if (window.hideInputError) {
										hideInputError(elems[i]);
									}
								} else {
									if (window.showInputError) {
										showInputError(elems[i]);
									}
								}
							}
						}});
					}
				}
			},
			setupOnSubmit:function(cfg) {
				if (typeof(cfg.form) == 'string') {
					cfg.form = document.getElementById(cfg.form);
				}

				cfg.form.onsubmit = function(e) {
					if (e) {
						e.stopPropagation();
						e.cancelBubble = true;
						e.returnValue = false;
					}
					var valid = true;

					for (var i = 0 ; i < cfg.inputs.length ; i++) {
						var elems = document.getElementsByName(cfg.inputs[i].name);
						var inputValid = isInputValid(cfg.inputs[i]);

						for (var j = 0 ; j < elems.length ; j++) {
							if (inputValid) {
								if (window.hideInputError) {
									hideInputError(elems[j]);
								}
							} else {
								valid = false;
								if (window.showInputError) {
									showInputError(elems[j]);
								}
							}
						}


					}

					if (valid) {
						if (window.hideError) {
							hideError();
						}
					} else {
						if (window.showError) {
							showError();
						}
					}

					if (e && valid) {
						e.returnValue = true;
					}

					return valid;
				};
			}
		};
	})();

	return {
		setupFormValidation:function(cfg) {
			if (typeof(cfg.form) == 'string') {
				cfg.form = document.getElementById(cfg.form);
			}

			cfg.blur = cfg.blur | true;

			if (cfg.blur) {
				Validator.setupOnBlur(cfg);
			}

			Validator.setupOnSubmit(cfg);
		},
		setupFormSubmission:function(cfg) {

		},
		setupForm:function(cfg) {
			this.setupFormValidation(cfg);
			this.setupFormSubmission(cfg);
		}
	};
})();
