var validate = {
	/** Highlight Farben für ein Fehlerfeld */
	HColors : new Array("#FCFECC", "#FCFECC","#FCFECC","#FFFFFF"),
	
	/** Merker (Array) fuer Fehlerfelder */
	errorField : "", 

	/** Highlight Farben intensitaet */
	intensity : 0,

	/** Highlight Farben aktiviert */
	aktiv : null,

	/** Metadaten für die Validierung, bzgl Dokumentation siehe wiki */
	elementMetas: {},

	/** Check Identifier für Längenbegrenzung */
	CHECK_LENGTH: "length",

	/** Check Identifier für Längenbegrenzung */
	CHECK_REQUIRED: "required",

	/** Check Identifier für Längenbegrenzung */
	CHECK_NUMBER: "number",

	/** Check Identifier für nur Buchstaben */
	CHECK_STRING: "string",
	
	/** Check Identifier für nur Buchstaben */
	CHECK_ALPHANUMERIC: "alphanumeric",

	/** Check Identifier für gültige Telefonnummer Zeichen */
	CHECK_PHONENUMBER: "phonenumber",
	
	/** Check Identifier für nur gültiges Wähungsformat (z.B. 1.000,00) */
	CHECK_CURRENCY_DE: "currencyde",
	
	/** Check Identifier für nur Alphanumerische Zeichen (z.B. Hausnr, PLZ) */
	CHECK_STREETNUMBER: "streetnumber",

	/** Check Identifier für gültiges PLZ_Format */
	CHECK_ZIP: "zip",

	/** Check Identifier für die erforderliche Auswahl von einem Element in einer Liste */
	CHECK_SELECT_ONE: "selectone",
	
	/** Check Identifier für die erforderliche Auswahl eines Radio Buttons */
	CHECK_RADIO_ONE: "checkedone",
	
	/** Check Identifier für die erforderliche Auswahl eines Radio Buttons */
	CHECK_AGB: "checkAGB",

	/** Parameter für maximale Länge */
	PARAM_MAXLENGTH: "maxLength",

	/** Parameter für maximale Länge */
	PARAM_MINLENGTH: "minLength",

	/** Parameter für Stellen vor dem Komma */
	PARAM_PRECISION_BEFORE_COMMA: "precisionBeforeComma",

	/** Parameter für Nachkommastellen */
	PARAM_PRECISION_AFTER_COMMA: "precisionAfterComma",

	getElementMeta: function(elementId) {
		var elementMeta = validate.elementMetas[elementId];
		if (immo.isEmpty(elementMeta)) {
			validate.elementMetas[elementId] = {};
			validate.elementMetas[elementId]["checks"] = {};
			elementMeta = validate.elementMetas[elementId];
		}
		return elementMeta;
	},

	registerCheckLength: function(elementId, errorAnchorName, maxLength, errorLabelId, minLength) {
		if (immo.isEmpty(maxLength)) {
			maxLength = 16;
		}
		if (immo.isEmpty(minLength)) {
			minLength = 0;
		}
		validate.getElementMeta(elementId)[validate.PARAM_MINLENGTH] = minLength;
		validate.getElementMeta(elementId)[validate.PARAM_MAXLENGTH] = maxLength;

		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_LENGTH);
	},


	registerCheckRequired: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_REQUIRED);
	},


	registerCheckNumber: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_NUMBER);
	},

	registerCheckString: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_STRING);
	},

	registerCheckAlphaNumeric: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_ALPHANUMERIC);
	},

	registerCheckPhoneNumber: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_PHONENUMBER);
	},
	
	registerCheckCurrencyDE: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_CURRENCY_DE);
	},
	
	registerCheckStreetnumber: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_STREETNUMBER);
	},

	registerCheckZip: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_ZIP);
	},

	registerCheckInteger: function(elementId, errorAnchorName, errorLabelId) {
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_BEFORE_COMMA] = 20;
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_AFTER_COMMA] = 0;
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_NUMBER);
	},

	registerCheckDecimal: function(elementId, errorAnchorName, errorLabelId) {
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_BEFORE_COMMA] = 3;
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_AFTER_COMMA] = 2;
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_NUMBER);
	},
	
	registerCheckEnergyValue: function(elementId, errorAnchorName, errorLabelId) {
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_BEFORE_COMMA] = 6;
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_AFTER_COMMA] = 4;
		validate.registerDelegate(elementId, errorAnchorName,errorLabelId, validate.CHECK_NUMBER);
	},

	registerCheckYear: function(elementId, errorAnchorName, errorLabelId) {
		validate.getElementMeta(elementId)[validate.PARAM_MINLENGTH] = 4;
		validate.getElementMeta(elementId)[validate.PARAM_MAXLENGTH] = 4;
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_LENGTH);

		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_BEFORE_COMMA] = 4;
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_AFTER_COMMA] = 0;
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_NUMBER);
	},

	registerCheckMoney: function(elementId, errorAnchorName, precisionAfterComma, errorLabelId) {
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_BEFORE_COMMA] = 10;
		if (immo.isStringEmpty(precisionAfterComma)) {
			precisionAfterComma = 2;
		}
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_AFTER_COMMA] = precisionAfterComma;
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_NUMBER);
	},

	registerCheckRoom: function(elementId, errorAnchorName, errorLabelId) {
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_BEFORE_COMMA] = 4;
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_AFTER_COMMA] = 1;
		validate.registerDelegate(elementId, errorAnchorName,errorLabelId, validate.CHECK_NUMBER);
	},

	registerSelectOne: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName,errorLabelId, validate.CHECK_SELECT_ONE);
	},
	
	registerCheckRadio: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName,errorLabelId, validate.CHECK_RADIO_ONE);
	},
	
	registerCheckAGB: function(elementId, errorAnchorName, errorLabelId) {
		validate.registerDelegate(elementId, errorAnchorName,errorLabelId, validate.CHECK_AGB);
	},
	
	registerCheckArea: function(elementId, errorAnchorName, errorLabelId) {
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_BEFORE_COMMA] = 9;
		validate.getElementMeta(elementId)[validate.PARAM_PRECISION_AFTER_COMMA] = 2;
		validate.registerDelegate(elementId, errorAnchorName, errorLabelId, validate.CHECK_NUMBER);
	},
	
	registerDelegate: function(elementId, errorAnchorName, errorLabelId, checkIdentifier) {
		validate.getElementMeta(elementId)["elementId"] = elementId;
		validate.getElementMeta(elementId)["checks"][checkIdentifier] = checkIdentifier;
		if (typeof errorAnchorName == "undefined") {
			errorAnchorName = null;
		}
		if (typeof errorLabelId == "undefined") {
			errorLabelId = null;
		}
		validate.getElementMeta(elementId)["errorAnchorName"] = errorAnchorName;
		validate.getElementMeta(elementId)["errorLabelId"] = errorLabelId;
		var element = document.getElementById(elementId);
		if(element.type == 'checkbox' || element.type == 'radio'){
			immo.addEvent(element, "click", validate.eventCheckCall);
		} else {
			//immo.addEvent(element, "keyup", validate.eventCheckCall); //hierauf reagiert der IE komisch (cursor kann nicht per Pfeiltaste im Feld zurueck bewegt werden; Tabsprung komisch)
			immo.addEvent(element, "change", validate.eventCheckCall);
			immo.addEvent(element, "blur", validate.eventCheckCall);
		}
	},


	eventCheckCall: function(event) {
		var elementId = null;
		if (event.target) {
			// Mozilla
			elementId = this.id;
			// oder event.target.id
		}
		else {
			// Internet Explorer
			elementId = event.srcElement.id;
		}
		var elementMeta = validate.getElementMeta(elementId);
		validate.validateField(elementMeta);
	},


	validateField: function(elementMeta) {
		var checksValid = true;
		var elementError = document.getElementById(elementMeta.elementId + "_error");
		if(elementError == null){
			elementError = document.getElementById("_error");
		}
		var elementErrorLabelId = document.getElementById(elementMeta.errorLabelId);

		for (var checkIdentifierKey in elementMeta["checks"]) {
			var checkIdentifier= elementMeta["checks"][checkIdentifierKey];
			var result = validate.dispatchElementValidation(elementMeta, checkIdentifier);
			checksValid &= result.valid;
			if (!result.valid) {
				// Fehlerfeld merken
				validate.errorField = elementMeta.elementId;
				// Fehler einblenden
				if(elementError != null){
					elementError.innerHTML = result.message;
					elementError.style.display = "block";
				}
				if(elementErrorLabelId != null){
					elementErrorLabelId.className = "contenthlerror";
				}
				break;
			}
		}
		if (checksValid) {
			// Fehler ausblenden
			if(elementError != null){
				elementError.style.display = "none";
			}
			if(elementErrorLabelId != null){
				elementErrorLabelId.className = "contenthlsmall";
			}
		}
		return checksValid;
	},


	validateFields: function() {
		var result = true;
		for (var elementMetaKey in validate.elementMetas) {
			var elementMeta = validate.elementMetas[elementMetaKey];
			var checksValid = validate.validateField(elementMeta);
			if (!checksValid) {
				if (!immo.isEmpty(elementMeta.errorAnchorName)) {
					var url = window.location.href;
					url = url.substring(url.indexOf("#"), url.lastIndexOf());
					window.location.href = url + "#" + elementMeta.errorAnchorName;
				}
				if(validate.aktiv == null){
					validate.aktiv = window.setInterval("validate.highlightOptions('"+elementMetaKey+"')", 250);
				}
				result = false;
				break;
			}
		}
		return result;
	},


	dispatchElementValidation: function(elementMeta, checkIdentifier) {
		var element = document.getElementById(elementMeta.elementId);
		if (!immo.isEmpty(element)) {
			var value = immo.ltrim(element.value);//wir wollen keine Leerzeichen
			element.value = value; //getrimmten Wert in Form zurueck schreiben
			if (checkIdentifier == validate.CHECK_LENGTH) {
				return validate.validateLength(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_NUMBER) {
				return validate.validateNumber(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_REQUIRED) {
				return validate.validateRequired(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_SELECT_ONE) {
				return validate.validateSelectOne(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_RADIO_ONE) {
				return validate.validateCheckRadio(elementMeta, element);
			}
			else if (checkIdentifier == validate.CHECK_AGB) {
				return validate.validateCheckAGB(elementMeta, element);
			}
			else if (checkIdentifier == validate.CHECK_STRING) {
				return validate.validateString(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_ALPHANUMERIC) {
				return validate.validateAlphaNumeric(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_PHONENUMBER) {
				return validate.validatePhoneNumber(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_CURRENCY_DE) {
				return validate.validateCurrencyDE(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_STREETNUMBER) {
				return validate.validateStreetNumber(elementMeta, element, value);
			}
			else if (checkIdentifier == validate.CHECK_ZIP) {
				return validate.validateZip(elementMeta, element, value);
			}
		}
	},


	validateLength: function(elementMeta, element, value, maxLength, minLength) {
		if(typeof(maxLength) == 'undefined' || maxLength == null) {
			maxLength = (elementMeta != null) ? elementMeta[validate.PARAM_MAXLENGTH] : 0;
		}
		if(typeof(minLength) == 'undefined' || minLength == null) {
			minLength = (elementMeta != null) ? elementMeta[validate.PARAM_MINLENGTH] : 0;
		}

		var result = new Object();

		if(value.length < minLength && value.length > 0){//wir duerfen nicht falsen, wenn kein Zeichen da ist (sonst wird das Feld zum Pflichfeld)
			result.valid = false;
			result.message = "Bitte geben Sie mind. " + minLength + " Zeichen ein.";
		}
		else if(value.length > maxLength){
			result.valid = false;
			result.message = "Bitte reduzieren Sie Ihre Eingabe auf " + maxLength + " Zeichen.";
		} 
		else{
			result.valid = true;
		}
		return result;
	},


	validateString: function(elementMeta, element, value) {
		var result = new Object();
		var re = new RegExp("^[A-Za-zÜüÖöÄäßÁáÀàÉéÈè]+[A-Za-zÜüÖöÄäßÁáÀàÉéÈè \s.,-/]*$");
		if (!re.test(value)) { // test returns true, if regexp successfull
			result.valid = false;
			result.message = "Bitte geben Sie nur Buchstaben ein.";
			return result;
		}
		result.valid = true;
		return result;		
	},


	validateAlphaNumeric: function(elementMeta, element, value) {
		var result = new Object();
		var re = new RegExp("^[0-9A-Za-zÜüÖöÄäßÁáÀàÉéÈè \s.,-]*$");
		if (!re.test(value)) { // test returns true, if regexp successfull
			result.valid = false;
			result.message = "Bitte geben Sie nur g&uuml;ltige Buchstaben oder Ziffern ein.";
			return result;
		}
		result.valid = true;
		return result;		
	},

	validateCurrencyDE: function(elementMeta, element, value) {
		var result = new Object();
		var re = new RegExp("^(?:\\d+|\\d{1,3}(?:\\.\\d{3})+)*?(?:,\\d+)*?$");
		if (!re.test(value)) { // test returns true, if regexp successfull
			result.valid = false;
			result.message = "Bitte geben Sie ein g&uuml;ltiges W&auml;hrungsformat ein. (Bsp. 1.000,00)";
			return result;
		}
		result.valid = true;
		return result;		
	},

	validateStreetNumber: function(elementMeta, element, value) {
		var result = new Object();
		var re = new RegExp("^[0-9]{1,5}[a-zA-Z0-9-., ]*?$");
		if (!re.test(value)) {
			result.valid = false;
			result.message = "Bitte geben Sie nur Ziffern oder Buchstaben ein. (Bsp: 8d oder 93a-c)";
			return result;
		}
		result.valid = true;
		return result;		
	},

	validatePhoneNumber: function(elementMeta, element, value) {
		var result = new Object();
		//var re = new RegExp("^((00|\+)\d{2}\s?)?(\(0\)\s)?(\d+\s?-?\s?)+$"); //prueft auf korrektes Tel-Format. Geht allerdings nur, wenn wir nicht jeden Tastenanschlag prüfen
		var re = new RegExp("^[0-9 \(\)\+/-]+$"); //prüft auf gültige Zeichen
		if (!re.test(value)) {
			result.valid = false;
			result.message = "Bitte geben Sie ein g&uuml;tiges Format ein. (Erlaubt: Ziffern, (, ), +, -, /)";
			return result;
		}
		result.valid = true;
		return result;		
	},


	validateZip: function(elementMeta, element, value) {
		var result = new Object();
		var re = new RegExp("^([A-Z]{0,3}[ ]?\-?[ ]?)?[0-9]*?$");
		if (!re.test(value)) {
			result.valid = false;
			result.message = "Bitte geben Sie ein g&uuml;ltiges PLZ-Format an. (Bsp: D-20097)";
			return result;
		}
		result.valid = true;
		return result;		
	},


	validateNumber: function(elementMeta, element, value) {
		var result = new Object();
		var regexClauseAfterComma = "(,[0-9]*)?";  // Nachkommastellenpruefung
		var re = new RegExp("^ *[0-9]*" + regexClauseAfterComma + " *$");
		if (!re.test(value) && !re.test(value.replace(".",""))) {
			result.valid = false;
			result.message = "Bitte geben Sie nur Ziffern ein.";
			return result;
		}

		var precisionAfterComma = elementMeta[validate.PARAM_PRECISION_AFTER_COMMA];
		if ((precisionAfterComma != null) && (typeof precisionAfterComma != "undefined")) {
			if (precisionAfterComma == 0) {
				regexClauseAfterComma = "";  // Nachkommastellenpruefung "ausschalten" für nachfolgende Schritte
				re = new RegExp("^ *[0-9]* *$");
				if (!re.test(value) && !re.test(value.replace(".",""))) {
					result.valid = false;
					result.message = "Bitte geben Sie nur Ziffern ein.";
					return result;
				}
			}
			else {
				re = new RegExp("^ *[0-9]*,?[0-9]{0," + precisionAfterComma + "} *$");
				if (!re.test(value) && !re.test(value.replace(".",""))) {
					result.valid = false;
					if (precisionAfterComma > 1) {
						result.message = "Bitte geben Sie nur " + precisionAfterComma + " Nachkommastellen ein.";
					}
					else {
						result.message = "Bitte geben Sie nur eine Nachkommastelle ein.";
					}
					return result;
				}
			}
		}

		var precisionBeforeComma = elementMeta[validate.PARAM_PRECISION_BEFORE_COMMA];
		if ((precisionBeforeComma != null) && (typeof precisionBeforeComma != "undefined")) {
			re = new RegExp("^ *[0-9]{0," + precisionBeforeComma + "}" + regexClauseAfterComma + " *$");
			if (!re.test(value) && !re.test(value.replace(".",""))) {
				result.valid = false;
				if (precisionBeforeComma > 1) {
					result.message = "Bitte geben Sie nur " + precisionBeforeComma + " Ziffern ein.";
				}
				else {
					result.message = "Bitte geben Sie nur eine Ziffer ein.";
				}
				return result;
			}
		}

		result.valid = true;
		return result;
	},


	validateRequired: function(elementMeta, element, value) {
		var result = new Object();
		if (immo.isStringEmpty(value)) {
			result.valid = false;
			result.message = "Bitte f&uuml;llen Sie das Feld aus.";
			return result;
		}
		result.valid = true;
		return result;
	},


	validateSelectOne: function(elementMeta, element,value) {
		var result = new Object();
		if (element.selectedIndex == -1) {
			result.valid = false;
			result.message = "W&auml;hlen Sie bitte eine Option aus.";
			return result;
		}
		result.valid = true;
		return result;
	},


	/**
	 * Überprüft, ob die AGB-Checkbox gecheckt ist
	 */
	validateCheckAGB: function(elementMeta, element) {
		var result = new Object();
		result = validate.validateCheckRadio(elementMeta, element); //das Validierungsverfahren ist identisch zu den Radios
		if(!result.valid) {
			result.message = "Bitte best&auml;tigen Sie, dass Sie die AGBs gelesen haben.";
		}
		return result;
	},


	/**
	 * Überprüft, ob ein Radio gecheckt ist
	 */
	validateCheckRadio: function(elementMeta, element) {
		var result = new Object();
		result.valid = false;
		var elements = document.getElementsByName(element.name); //Radio-Elemente mit gleichem Namen wie elementId speichern
	    for(var i=0; i<elements.length; i++){ //Radio-Gruppe per elementName durchlaufen
	        if(elements[i].checked) {
				result.valid = true;
			}
		}
		if(!result.valid) {
			result.message = "W&auml;hlen Sie bitte eine Option aus.";
		}
		return result;
	},
	

	highlightOptions:function (elementid){
		var element = document.getElementById(elementid);
		element.style.backgroundColor = validate.HColors[validate.intensity];

		validate.intensity++;
		if(validate.intensity > validate.HColors.length){
			window.clearInterval(validate.aktiv);
			validate.aktiv = null;
			validate.intensity = 0;
		}
	}
	
}
