
//Stores our tiny fields
var tinyElements = new Array();

function tinyOninit(){
	/*
	var tinylist = tinyMCE.getParam('elements');
	tinylist = tinylist.split(',');
	tinyElements.push(tinylist);
	*/
}

function addToOnload(event){
	onloadEvents.push(event);
	window.onload = function() { 
		for (var x = 0; x < onloadEvents.length; x ++) {
			eval(onloadEvents[x]);
		}
	}
}

var DocumentEvents = Object();
var EventHandler = {
	attachEvent : function(id, EHonEvent, EHmyFunc){
		if (!EventHandler.hasEvent(id,EHonEvent)){
			DocumentEvents[id+EHonEvent] = new Array();
		}
		var params = new Array();
		if (arguments.length > 3){
			for (var i = 3; i < arguments.length; i++){
				params.push(arguments[i]);
			}
		}
		DocumentEvents[id+EHonEvent].push({onEvent : EHonEvent, myFunc : EHmyFunc, myParams : params});
	},
	hasEvent : function (id, EHonEvent){
		//Check if this id has an event
		var test = DocumentEvents[id+EHonEvent];
		if (test){
			return true;
		} else {
			return false;
		}
	},
	idEvents : function (id,EHonEvent ){		
		return (DocumentEvents[id+EHonEvent]);
	},
	loadEvents : function (){
		for (var et in DocumentEvents){
			var idAndEvent = EventHandler.getIdAndEvent(et);		
			if (idAndEvent){
				var eventList = DocumentEvents[et];				
				EventHandler.run(idAndEvent[0], idAndEvent[1], eventList);	
			}
		}
		//Now clear the EventsArray
		DocumentEvents = new Object();
	},
	getIdAndEvent: function (myString){
		
		var reg = new RegExp("([A-Za-z0-9_]+)(onchange|onblur|onkeyup|onclick)");
		try {
			var matches  = myString.match(reg);
			return ([matches[1],matches[2]]);	
		}
		catch (e) {
			return false;	
		}
	},
	run: function (id, myEvent, eventList){
		var element = idE(id);		
		if (element){
			var myFunc = EventHandler.generateRunFunc(eventList);
			element[myEvent] = myFunc; 	
		}
	}, 
	/**
	 * @return function
	 */
	generateRunFunc: function(eventList){
		return(function(){
			var self = this;
			for (var i=0; i < eventList.length; i++){
				//Generate Arg String if we have Params
				var eventObj = eventList[i];
				EventHandler.callFunc.call(self,eventObj.myFunc,eventObj.myParams);
			}
			return false;
		});
	},
	/**
	 * Calls a user function with arguments.
	 */
	callFunc : function (funcName, params){
		
		var paramString = '';	
		if (params.length > 0){
			for (var y = 0; y < params.length;y++){
				paramString += ',params['+y+']';	
			}	
		}
		var self = this;
		eval("var myCall = " +funcName+".call(self"+paramString+")");
		if (typeof myCall == 'function'){
			myCall();
		}
	}
}

/*** String functions ***/
//Option is to add these methods as prototypes of String. 
var stringTools = {	
	trim: function(str){
		return str.replace(/^\s+/, '').replace(/\s+$/, '');		
	},
	/**
	checks and validates string type. 
	eg. to check for a numeric string of max length 4 = str, numeric, 0,4
	eg. to check a string of length 5 chars = str, string, 5,5
	returns boolean
	*/ 
	check: function(str, type, params)
	{
		str = stringTools.trim(str);	
		min = Number(params[0]) || 1;
		max = Number(params[1]) || '';		
			
		//Check if there are more than 2 params. If there are, the extra ones are values this str cannot equal
		if (params.length > 2){
			for (var i = 2; i < params.length; i++){
				if (str == params[i]) return false;
			}
		}	
		//Simple string checks.
		if (type == 'string' && (min >  0 &&  (max == '' || max == 0))){
			return str.length >= min ? true : false;			
		}
		//check if both are the same
		exactMatch = min == max ? true : false;
		if (exactMatch){
			repetitionExp = '{'+min+'}';
		} else {
			repetitionExp = '{'+min+','+max+'}';			
		}
		switch (type) {
			case "string" : exp = "."; break;
			case "alpha" : exp = "[a-z]"; break;
			case "numeric" : exp = "[0-9 ]"; break;
		}				
		regEx = new RegExp("^"+exp+repetitionExp+"$","i");		
		return  str.search(regEx) != -1 ;
	}
}

/** This adds an onsubmit to the form in FormValidator  ***/
function validateOnSubmit(formValidator, ajaxOptions){	
	var myForm = idE(formValidator.myForm);		
	var myFunc = submitForm(formValidator, ajaxOptions);	
	myForm.onsubmit = myFunc;
}
/**
 * Returns the function that is called by the form onsubmit
 * @param {Object} formValidator
 * @param {Object} ajaxOptions
 */
var submitForm = function (formValidator, ajaxOptions){	
	return (function(){		
	
	//var valid = false;
		var valid =  formValidator.initSubmitValidation();		
		if (ajaxOptions){			
			if(valid){
				AjaxLoader.formSubmit(formValidator.myForm, ajaxOptions);	
			}
			return false;
		} else {
			return valid;	
		}});
}

/************** FORM VALIDATOR OBJECT *******************/
var FormValidator = function(formId){
	this.myForm = formId;
	this.validationRules = [];
}

FormValidator.prototype = {
	//Define validation for element
	defineValidation : function (element, type, validationArgs){
		
		//Set some vars for the validationRule object.
		var vR = new ValidationRule(element, validationArgs);	
		vR.formName = this.myForm;
		var myForm = idE(this.myForm);
		
		vR.asset = this.asset;
		//check if its a date check. This element won't exist so get the day element.
		if (type == 'date'){			
			var elementName = element+'[Day]';
		} else {
			var elementName = element;
		}
		
		//Set the vR element name
		vR.element = elementName;		
		var element = myForm.elements[elementName];
		
		var p  = new RegExp("\\w+\\[(\\d)\\]\\[\\w+\\]");
		//Set type if it isn't a date check
		if (type != 'date'){
			try {
				//get the type
				type = element.type.toLowerCase();
				//Get the asset number of this field. eg ASSET[INT][FIELD] etc. this sets the INT
				/*var matches  = element.name.match(p);
				if (matches){
					vR.assetNumber = matches[1];	 
				}*/
			} catch (e){			
				if (type == 'checkbox'){
					vR.element = elementName + '[]';
					element = myForm.elements[vR.element];
					type = element[0].type.toLowerCase();
				}
			}
		}
		vR.type = type;
		vR.myForm = this.myForm;
		
		//Add this into the validation rules list
		this.validationRules.push(vR);
		
		//Also append the event to the element we are checking
		addValidationEvent.create(vR,element);
		
	},
	
	listRules : function (){	
		for (var i=0; i < this.validationRules.length; i++) {
			vR = this.validationRules[i];
		}
	},	
	//This iterates through all our rules and checks em
	//Also sets focus to the first incorrect field
	initSubmitValidation : function (){
		//error counter
		error = 0;		
		for (ii =0 ; ii < this.validationRules.length ; ii++){			
			vRule = this.validationRules[ii];
			valid = vRule.validate();			
			//if its valid do nothing, else increment		
			if (!valid){
				if (error == 0){
					try {
						var e = document.forms[this.myForm].elements[vRule.element];
						e.focus();
					} catch (e) {
						//Silent
					}
				}
				error++;
			}
		}		
		//If error is > 0 we have errors so return false
		if (error > 0){		
			return false;
		} else {		
			return true;	
		}
		return false;	
	}
}

/*************** Validation Rule Object ********************/
var ValidationRule = function(element, validationArgs){	
	this.divId = validationArgs.divId || element;		
	this.errorMessage = validationArgs.eMsg || 0;
	this.validationFunc = validationArgs.vFunc || 0;
	this.params = validationArgs.args ||  [];
	//While we create the rule, hide the error message divs if they exist.
}

//Validate prototype function for ValidationRule
ValidationRule.prototype = {
	validate : function(){	
		if (this.type == 'datetime' || this.type == 'date'){			
			eval("isValid = validateRule." + this.validationFunc + "(this.myForm, this.divId)");	
		} else {
			
			//Check if any arguments were passed. First arg is the element - onblur, onchange etc. 
			
			if (arguments.length > 0){
				var obj = arguments[0];				
				if(typeof obj == 'object'){
					var obj = document.forms[this.myForm].elements[this.element];	
				}
			} else {
				//Need to define obj as the element. This is called from the onsubmit check function
				var obj = document.forms[this.myForm].elements[this.element];				
			}
			
			if (this.validationFunc == 'fieldDependency' || this.validationFunc == 'matchElementValue'){				
				var p  = new RegExp("(\\w+)\\[(\\d)\\]\\[\\w+\\]");
				var matches = this.element.match(p);
				var dName = matches[1]+'['+matches[2]+']'+'['+this.params[0]+']';
				var myForm = idE(this.myForm);			
				var isValid = validateRule[this.validationFunc](obj,myForm.elements[dName], this.params, this.type);
			} else if (this.validationFunc == 'thisOrThat'){
				var p  = new RegExp("(\\w+)\\[(\\d)\\]\\[\\w+\\]");
				var matches = this.element.match(p);
				var dName = matches[1]+'['+matches[2]+']'+'['+this.params[0]+']';
				var myForm = idE(this.myForm);			
				var isValid = validateRule[this.validationFunc](obj,myForm.elements[dName], this.params, this.type);
			} else {
				try { //Catch errors
					var isValid = validateRule[this.validationFunc](obj,this.params, this.type);					
				} catch (e){
					//					
				}
				
			}
		}
		if (!isValid){
			var element = document.forms[this.myForm].elements[this.element];
			displayMessage.buildId(element, this.errorMessage, this.type);
			//displayMessage.inId(this.divId+'_msg', this.errorMessage);
		} else {
			if (this.type == 'checkbox'){
				var errDiv = this.element;
			} else {
				var errDiv = this.type == 'date' ? this.divId+'[Day]' : this.divId;	
			}
			
	 		displayMessage.flush(errDiv+'_msg');		
		}
		return isValid;
	}
}

/****************** Validation Event ***********************/
var addValidationEvent = {		
	getValidateFunc: function (vR, validKey){				
		//Check if we need a valid key function
		validKey = validKey || false;
		if (validKey){
			return (function (event){ if (validateRule.isValidKeyStroke(event)) vR.validate(this);	});	
		} else {
			return (function (){vR.validate(this);});
		}
	},		
	create: function (vR, element){
		var type = vR.type;
		if (vR.type == 'radio')	type = 'checkbox'; //Check boxes behaviour 
		if (vR.type == 'date') type = 'datetime';
		if (vR.type == 'select-one' || vR.type == 'select-multiple')	type = 'select';
		
		switch (type){
			case 'text':
								
				element.onkeyup = addValidationEvent.getValidateFunc(vR, true);
				//element.onblur = addValidationEvent.getValidateFunc(vR);
				
				EventHandler.attachEvent(element.id, 'onblur','addValidationEvent.getValidateFunc',vR);
			break;
			case 'textarea':	
				//element.onblur = addValidationEvent.getValidateFunc(vR);
			break;
			case 'select':
				vR.validationFunc = 'isSelected';
				//Check if this element has an on change event already assigned
				EventHandler.attachEvent(element.id, 'onchange','addValidationEvent.getValidateFunc',vR);
			break;
			case 'checkbox':
				//Need to add an onclick to each on of these checkboxes	
				if (element.length){
					vR.validationFunc = 'isChecked';	
					for (var i=0; i < element.length; i++){
			   			element[i].onclick = function (){							
							vR.validate(element);
		   				}
	   				}
				}
			break;	
            case 'datetime':                
				//get day, month , year and set onChange to validate.
				var fields = ['[Day]','[Month]','[Year]'];
				/* CHECK THIS ON SUBMIT INSTEAD
				for (var i = 0; i < fields.length ; i++){
					document.forms[vR.formName].elements[vR.divId+fields[i]].onchange = function(){
						vR.validate(this);
					}
				}*/
            break;			
		}
	}
}


/******************** Validation Rules *********************/

var validateRule = {
	//Check if the type is a string (anything really). params is an array. 1st is minimum, 2nd is max chars	
	isString: function (element , params, type){	
		val = element.value || '';	
		paramList = params || [];
		
		if (type == 'textarea'){
			try {
				var tinyInt = tinyMCE.getInstanceById(element.name);
				if (tinyInt){				
					val = tinyInt.getBody().innerHTML;
					//Strip tags
					val = val.replace(/<\/?[^>]+>/gi, '');
					//If the string empty, then set value as empty
					if (val == '<br>' || val == '&nbsp;'){
						val = '';
					}
				}
			} catch (e){
				//alert('line 376');
			}
		}
        return stringTools.check(val, 'string',paramList);		
	},
	fieldDependency : function (element, dependantElement, params, type){
		if (dependantElement.value == params[1]){
			val = element.value || '';
			return stringTools.check(val, 'string',[1,0]);	
		}
		return true;
	},
	hasValueValidate : function (element, params){
		//First check if this element has any values, if it does then validate it
		var val = element.value || '';	
		var paramList = [1,0];
		
		if (stringTools.check(val, 'string',paramList)){
			//Get Validate Func. 
			if (params[0]){
				var correctParams = params.slice(0);
				var junk = correctParams.shift();
				return validateRule[params[0]](element,correctParams);	
			} else {
				return false;
			}
		} else {
			return true;
		}
	},
	thisOrThat : function (thisElement, thatElement, params) {
		var thisVal = thisElement.value || '';
		var thatVal = thatElement.value || '';
		
		if (!stringTools.check(thisVal, 'string',[1,0]) && !stringTools.check(thatVal, 'string',[1,0]) ){
			return false;			
		} return true;
	},
	// is it alpha only 
	isAlpha: function (element, params){	    
        val = element.value || '';
		paramList = params || [];
		return stringTools.check(val,'alpha',paramList);
	},
	/**
	 * 
	 * @param {Object} element
	 * @param {Object} params
	 */
	isRegExp : function (element,params){
		regEx = new RegExp(params[0],"i");
		return regEx.test(element.value);
	},
	/**
	 * Check that two element values are equal to each other.( used for confirmations )
	 * @param {Object} element
	 * @param {Object} params
	 */
	matchElementValue: function(element, dependantElement, params){
		if (element.value != dependantElement.value)
			return false;
		
		return true;
	},
	/**
	 * Check thats its just a number 
	 * @param {Object} element
	 * @param {Object} params
	 */
	//is it numeric only
	isNumeric: function (element, params){
		val = element.value || '';
		paramList = params || [];
		return stringTools.check(val,'numeric',paramList);
	},

    //Is it a datetime value
    isDateTime: function (myForm, ePrefix){
		var myForm = idE(myForm);
		var MonthDays = new Array(31,28,31,30,31,30,31,31,30,31,30,31);  		
		var day = myForm.elements[ePrefix+'[Day]'].value;
		var month = myForm.elements[ePrefix+'[Month]'].value;
		var year = myForm.elements[ePrefix+'[Year]'].value;
		
		dayLimit = MonthDays[month-1];
		if (day > dayLimit)	{			
			return false;
		}
		if (day == '' || month == '' || year == '')	{			
			return false;
		}
		return true;
    },
	
	// is it an email
	isEmail: function(element){
		var element = idE(element);
		return (element.value.search(/^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/) != -1);
	},
	
	//Is this box checked
	isChecked: function (element){
		
		if (typeof element == 'string'){
			element = idE(element);			
		}
		var foundValue = false;
		if (element){
			for (var i=0; i < element.length; i++){				
		   		if (element[i].checked){
		   			foundValue = true;
	   			}
   			}
   		}
		return foundValue;
	},
	
	//Selection boxes.		
	isSelected: function (element, params){
		
		index = element.selectedIndex;	
		
		var selected =  (element.options[index].value == '') ? false : true;
		var val = element.options[index].value;
		
		//Check if there are more than 2 params. If there are, the extra ones are values this str cannot equal
		if (params.length > 2){
			for (var i = 2; i < params.length; i++){
				if (val == params[i]) return false;
			}
		}
		
		var otherId = replaceErrDiv(element.name) + '_other';		
		return selected;
	},
	//Clear the other select box 	
	clearOther: function (element){
		otherId = replaceErrDiv(element.name) + '_other';		
		msgId = replaceErrDiv(element.name)+'[other]_msg';
		
		displayMessage.flush(otherId); displayMessage.flush(msgId);
	},	
	//This determines if its a valid keystroke to initiate validation
	isValidKeyStroke: function(e){
		var e = window.event  || e;
		try {
			var key = e.keyCode || e.which;
		} catch (e){
			var key = 0;
		}
		var keychar = String.fromCharCode(key);		
		//9 - tab, 8 - backspace, 46 - delete, 27 - escape, 16 shift, 35 - end, 36 home
		if (key == 9 || key == 27 || key ==16 || key == 35 || key == 36){
			return false;
		}
		return true;
	}
}


//Message Display
var displayMessage = {
	
	//displays the innerHtml of id with msg
	inId: function (id, msg){
		
        id = replaceErrDiv (id);
		obj = idE(id);
		//set the parent class
		displayMessage.findAndSetParentClass(obj, false, 2);
		if (obj){
			obj.innerHTML = '<div class="formErrorMessage">'+msg+'</div>';
			obj.style.display = "block";
			obj.style.visibility = "";
		}
	},
	//displays the innerHtml of id with msg
	buildId: function (element, msg, type){       
		//set the parent class		
		if (type == 'checkbox' || type == 'radio'){
			var errorid =  replaceErrDiv (element[0].name+'_msg');		
		} else {
			var errorid = replaceErrDiv (element.name+'_msg');		
		}
		errorDiv = document.getElementById(errorid);
		if (!errorDiv){
			displayMessage.findAndSetParentClass(element, false, 2);				
			msgElement = document.createElement('div');
			msgElement.setAttribute('id',errorid);
			msgElement.className = 'formErrorMessage';
			msgElement.appendChild(document.createTextNode(msg));
			
			if (type == 'checkbox' || type == 'radio'){
				//if its a radio or checkbox, attach the message after the last element
				element[element.length-1].parentNode.appendChild(msgElement);
			} else {
				element.parentNode.appendChild(msgElement);
			}
		}
	},
	//Removes the Id from the document.
	//using parentNode.removeChild
	flush: function (id){
        id = replaceErrDiv(id);
		obj = idE(id);
		displayMessage.findAndSetParentClass(obj, true, 2);		
		if (obj){
			obj.parentNode.removeChild(obj);
		}
	},	
	findAndSetParentClass: function (myElement, flushClass,  limit ){
		if (limit >0){
			limit = limit - 1;
			try {
				var parentClassName = myElement.parentNode.className;
				if (parentClassName == '' || parentClassName == 'invalidInputArea'){
					if (flushClass){
						myElement.parentNode.className = '';
					} else {
						myElement.parentNode.className = 'invalidInputArea';
					}
				} else {
					pNode = myElement.parentNode;
					if (pNode){
						findAndSetParentClass(myElement.parentNode,flushClass, limit);
					}
				}
			} catch (e){
				
			}
		}	
	}
}

function replaceErrDiv(str){
    var newStr = '';
    for (i = 0; i < str.length; i ++){
        charStr = str.charAt(i);
        if (charStr == '[' || charStr == ']'){
            charStr = '_';
        }
        newStr += charStr;
    }    
    return newStr;
}

function idE(elementId){	
	if (typeof elementId == 'string'){
		var e = document.getElementById(elementId);
	} else {
		var e = elementId;
	}
	return e;
}
