
function validate_errmsg(element, valid, errmsg) {
	if(!valid && errmsg != null) {
		alert(errmsg + '; wartość: ' + element.value);
	}
}

function validate_regex(element, regex, errmsg) {
	var res = element.value.match(regex);
	validate_errmsg(element, res, errmsg);
	return res;
}

function validate_isNotEmpty(element, errmsg) {
	var regExpr = /.+/;
	return validate_regex(element, regExpr, errmsg);
}

function validate_isEmail(element, errmsg) {
	var regExpr = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
	return validate_regex(element, regExpr, errmsg);
}

function validate_isNumber(element, errmsg) {
	var regExpr = /^[-]?\d*\.?\d*$/;
	return validate_regex(element, regExpr, errmsg);
}

function validate_isSmGrE(element, val, errmsg, type) {
	var res = true;
	if(element.value.length > 0) {
		res =  
			((type == 'e' && val == element.value)
			|| (type == 'se' && element.value <= val)
			|| (type == 'ge' && element.value >= val)
			|| (type == 's' && element.value < val)
			|| (type == 'g' && element.value > val));
	}
	return res;
}

function validate_isNumberSmGrE(element, val, errmsg, type) {
	var res = validate_isNumber(element, errmsg);
	if(res) {
		var smGrERes = validate_isSmGrE(element, val, errmsg, type);
		res = res && smGrERes;
		validate_errmsg(element, res, errmsg);
	}
	return res;
}

function validate_isNumberSm(element, val, errmsg) {
	return validate_isNumberSmGrE(element, val, errmsg, 's');
}
function validate_isNumberSmE(element, val, errmsg) {
	return validate_isNumberSmGrE(element, val, errmsg, 'se');
}
function validate_isNumberGr(element, val, errmsg) {
	return validate_isNumberSmGrE(element, val, errmsg, 'g');
}
function validate_isNumberGrE(element, val, errmsg) {
	return validate_isNumberSmGrE(element, val, errmsg, 'ge');
}
function validate_isNumberE(element, val, errmsg) {
	return validate_isNumberSmGrE(element, val, errmsg, 'e');
}

function validate_isInteger(element, errmsg) {
	var regExpr = /^[-]?\d*$/;
	return validate_regex(element, regExpr, errmsg);
}

function validate_isIntegerSmGrE(element, val, errmsg, type) {
	var res = validate_isInteger(element, errmsg);
	if(res) {
		res = res && validate_isSmGrE(element, val, errmsg, type);
		validate_errmsg(element, res, errmsg);
	}
	return res;
}
function validate_isIntegerSmE(element, val, errmsg) {
	return validate_isIntegerSmGrE(element, val, errmsg, 'se');
}
function validate_isIntegerGr(element, val, errmsg) {
	return validate_isIntegerSmGrE(element, val, errmsg, 'g');
}
function validate_isIntegerGrE(element, val, errmsg) {
	return validate_isIntegerSmGrE(element, val, errmsg, 'ge');
}
function validate_isIntegerE(element, val, errmsg) {
	return validate_isIntegerSmGrE(element, val, errmsg, 'e');
}

function validate_isDate(element, splitter) {
	var arrDate = element.value.split(splitter);
	var res = false;
	//TODO chwilowo zakladamy, ze data jest w formacie rrrr-mm-dd
	if(arrDate.length == 3) { 
		var m = arrDate[1] - 1; var d = arrDate[2]; var r = arrDate[0];
		var date = new Date();
		date.setDate(d);
		date.setMonth(m);
		date.setFullYear(r);
		if (date.getFullYear() == r && date.getMonth() == m && date.getDate() == d) {
	    	//data jest poprawna
	    	res = true;
		}
	}
	return res;
}


// ------------------------- FormFieldValidator - start ------------------------------------

function FormFieldValidator_decorateField(showEmptys) {
	if(!this.isValid()) {
		// blad
		this.setDecoration('error');
	} else if(this.isRequisite()) {
		if(this.isEmpty() && showEmptys) {
			this.setDecoration('error');
		} else {
			// wymagane
			this.setDecoration('requisite');
		}
	} else if(this.isImportant()) {
		// pozadane
		this.setDecoration('important');
	} else {
		// normalny tryb
		this.setDecoration('common');
	}
}

function FormFieldValidator_setDecoration(decorationType) {
	var clName = this.getElementClass(this.element.type, decorationType);
	if(clName != null && clName.length > 0) this.element.className = clName;
	else if(decorationType == 'error') this.element.style.backgroundColor = 'red'; // zeby pokazalo error nawet jak nie ma klasy
}

function FormFieldValidator_fireChange() {
	this.validateShow(false);
	// przechodzimy po wszystkich zarejestrwanych odbiorcach zdarzenia zmiany
	for(var i = 0; i < this.onChangelisteners.length; i++) {
		this.onChangelisteners[i].onChange(this.element.value);
	}
}

function FormFieldValidator_toElement(elementId) {
	var element = document.getElementById(elementId);
	element.focus();
	if(element.select) element.select();
}

function FormFieldValidator_beforeMovingToElement(elementId) {

}

function FormFieldValidator() {
	this.onChangelisteners = null;
	this.elementId = null;
	this.valid = false;
	this.element = null; // bedzie mial wartosc po polaczeniu metoda joinHTML
	this.paramName = null;
	this.validatingFunction = function () {
		return true;
	}
	this.event = null;
	
	// metody
	
	/**
	 * Rejestruje odbiorce zdarzenia zmiany wartosci elementu (to samo zdarzenie ktorego nazwe podajemy do metody init
	 * i ktore powoduje rowniez przeprowadzenie validacji).
	 */
	this.addListener = function (listener) {
		this.onChangelisteners.length = this.onChangelisteners.length + 1;
		this.onChangelisteners[this.onChangelisteners.length - 1] = listener;
	}
	
	this.init = function (elementId, validatingFunction, paramName, event) {
		this.onChangelisteners = [];
		this.elementId = elementId;
		this.valid = false;
		this.element = null; // bedzie mial wartosc po polaczeniu metoda joinHTML
		this.paramName = paramName;
		this.event = event;
		this.validatingFunction = validatingFunction;
		this.joinHTML();
	}
	
	this.isRequisite = function () {
		return false;
	}

	this.isImportant = function () {
		return false;
	}
	
	this.isValid = function () {
		return this.valid;
	}
	
	this.isVisible = function () {
		return true;
	}
	
	this.isEmpty = function () {
		return this.element.value.length == 0;
	}
	
	this.validate = function (showEmptys) {
		this.valid = this.validatingFunction != null ? this.validatingFunction() : true;
		this.decorateField(showEmptys);
		return this.valid;
	}
	this.getErrMsg = function () {
		return 'Parametr \"' + this.paramName + '\" ma niepoprawną wartość: ' + this.element.value;
	}
	this.getEmptyMsg = function () {
		return 'Wymagany parametr \"' + this.paramName + '\" nie posiada wartości';
	}
	this.getParamName = function () {
		return this.paramName;
	}

	this.beforeMovingToElement = FormFieldValidator_beforeMovingToElement;

	/**
	 * Sprawdza czy pole ma prawidlowa wartosc lub puste, przenowsi do pierwszego znalezionego pola.
	 * @param boolean showEmptys czy zmieniac wyglad pola pustego (wymaganego).
	 */
	this.validateShow = function (showEmptys) {
		this.validate(showEmptys);
		var res = true;
		if(!this.valid) {
			alert(this.getErrMsg());
			this.beforeMovingToElement(this.elementId);
			setTimeout("FormFieldValidator_toElement('" + this.elementId + "')", 0);
			res = false;
		} else if(this.isRequisite() && this.isEmpty()) {
			alert(this.getEmptyMsg());
			// przejscie do elementu
			this.beforeMovingToElement(this.elementId);
			setTimeout("FormFieldValidator_toElement('" + this.elementId + "')", 0);
			res = false;
		}
		return res;
	}

	this.getValidateMsgs = function () {
		this.validate(true);
		var res = true;
		if(!this.valid) {
			return this.getErrMsg();
		} else if(this.isRequisite() && this.isEmpty()) {
			return this.getEmptyMsg();
		}
	}

	this.fireChange = FormFieldValidator_fireChange;
	 
	this.joinHTML = function () {
		this.element = document.getElementById(this.elementId);
		this.element.validator = this;
		if(this.event != null) {
			this.element[this.event] = function() {
				this.validator.fireChange();
			}
		}
		this.validate(false);
	}
	/**
	 * Metoda podaje nazwe klasy, ktora powinna byc przypisana do elementu w zaleznosci od jego statusu.
	 * elementType to wartosc atrybutu type elementu formularza.
	 * statusType moze przyjmowac wartosci: 'requisite' (wymagany), 'important' (wazny), 'common' (zwykły), 'error' (blad wartosci)
	 * 'invisible' (niewidoczny).
	 * jezeli bedzie miec inna wartosc zostanie potraktowany jak common.
	 * Jezeli zwroci null to klasa nie zostanie uzyta.
	 */
	this.getElementClass = function (elementType, statusType) {
		return null;
	}
	this.setDecoration = FormFieldValidator_setDecoration;
	this.decorateField = FormFieldValidator_decorateField;

}

// ------------------------- FormFieldValidator - koniec -----------------------------------


function BaseFormMediator() {
	this.fieldValidators = null;
	this.config = {};
	this.config.dbTrue = 'T';
	this.initBaseMediator = this.init;
	this.initBaseFormMediator = function() {
		this.initBaseMediator();
		this.fieldValidators = [];
	};
	this.init = function() {
		this.initBaseFormMediator();
	};
	this.addFieldValidator = function (fieldValidator) {
		this.fieldValidators.length = this.fieldValidators.length + 1;
		this.fieldValidators[this.fieldValidators.length - 1] = fieldValidator;
	};
	this.removeFieldValidatorById = function (fieldId) {
		var newFieldValidators = [];
		for(var i = 0; i < this.fieldValidators.length; i++) {
			if(this.fieldValidators[i].elementId != fieldId) {
				newFieldValidators.length = newFieldValidators.length + 1;
				newFieldValidators[newFieldValidators.length - 1] = this.fieldValidators[i];
			}
		}
		this.fieldValidators = newFieldValidators;
	};
	this.validate = function(showEmptys) {
		var res = true;
		for(var i = 0; i < this.fieldValidators.length; i++) {
			res = res && this.fieldValidators[i].validate(showEmptys);
			//alert('Walidacja elementu: '+ this.fieldValidators[i].element.name + ' res: ' + res);
		}
		// jezeli nie przeszla poprawnie cala validacja, to poszukujemy pierwszego elementu, ktory ma niepoprawna wartosc i przenosimy
		// do niego
		//if(!res) {
			for(var i = 0; i < this.fieldValidators.length; i++) {
				if(!this.fieldValidators[i].validateShow(showEmptys)) return false;
			}
		//}
		return res;
	}
	
	this.getValidateMsgs = function () {
		var msgs = [];
		for(var i = 0; i < this.fieldValidators.length; i++) {
			var msg = this.fieldValidators[i].getValidateMsgs();
			if(msg != null) {
				msgs[msgs.length] = msg;
			}
		}
		return msgs;
	}
	
	this.getFieldValidators = function () {
		return this.fieldValidators;
	}
}
BaseFormMediator.prototype = new BaseMediator();

function getValuePaarArr(paar) {
	if(paar)
		return paar.split(',');
	else
		return null;
}


function DefFormFieldValidator() {
	this.mediator = null;
	this.mode = 'common';
	this.errorClass = '';
	this.normalClass = '';
	
	this.initDefFormFieldValidator = function (mediator, elementId, mode, funkcjaValidujaca, nazwaParametru, event, normalClass, errorClass) {
		this.mediator = mediator;
		this.mode = mode;
		this.mediator.addFieldValidator(this);
		this.errorClass = errorClass;
		this.normalClass = normalClass;
		this.init(elementId, funkcjaValidujaca, nazwaParametru, event);
	}
	
	this.isRequisite = function () {
		return this.mode == 'requisite';
	}
	this.isImportant = function () {
		return this.mode == 'important';
	}
	this.isVisible = function () {
		return this.mode !== 'invisible';
	}
	this.getElementClass = function (elementType, statusType) {
		var typ = null;
		if(this.element.type == 'text') typ = 'text';
		else if(this.element.type == 'textarea') typ = 'textarea';
		else if(this.element.type == 'select-one' || this.element.type == 'select-multiple') typ = 'select';
		else if(this.element.type == 'checkbox') typ = 'checkbox';
		//if(statusType == 'common') return 'eproisn_' + typ; 
		//return 'eproisn_'+ statusType + '_' + typ;
		if(statusType == 'error') return this.errorClass;
		
		return this.normalClass;
	}
}
DefFormFieldValidator.prototype = new FormFieldValidator();

function DefSelectFieldValidator() {
	this.initDefSelectFieldValidator = function (mediator, elementId, mode, funkcjaValidujaca, nazwaParametru, normalClass, errorClass) {
		this.initDefFormFieldValidator(mediator, elementId, mode, funkcjaValidujaca, nazwaParametru, 'onchange', 
			normalClass, errorClass);
	}
	this.isEmptyOld = this.isEmpty;
	this.isEmpty = function () {
		return this.isEmptyOld() && this.element.options.length > 0;
	}
}
DefSelectFieldValidator.prototype = new DefFormFieldValidator();

function DefSelectDescrFieldValidator() {
	this.validatorSelect = null;
	/*
	 * @param mediator
	 * @param elementId id opcjonalnego elementu opisowego.
	 * @param nazwaParametru nazwa parametru (opisowa).
	 * @param ZlecenieedSelectField validatorSelect obiekt validatora elementu select od ktorego wartosci zalezy wyswietlanie elementu opcjonalnego.
	 * @param spWysw sposob wyswietlania elementu opcjonalnego (inline/block). 
	 */
	this.initDefSelectDescrFieldValidator = function (mediator, elementId, nazwaParametru, validatorSelect, spWysw, normalClass, errorClass) {
		this.validatorSelect = validatorSelect;
		this.validatorSelect.addListener(this);
		this.spWysw = spWysw;
		this.initDefFormFieldValidator(mediator, elementId, 'common', null, nazwaParametru, 'onchange', normalClass, errorClass);
	}
	this.isRequisite = function () {
		var paar = getValuePaarArr(this.validatorSelect.element.value);
		if(paar != null && paar[1] == this.mediator.config.dbTrue) {
			return this.validatorSelect.isRequisite();
		}
		return false;
	}
	this.isImportant = function () {
		var paar = getValuePaarArr(this.validatorSelect.element.value);
		if(paar != null && paar[1] == this.mediator.config.dbTrue) {
			return this.validatorSelect.isImportant();
		}
		return false;
	}
	this.isVisible = function () {
		var paar = getValuePaarArr(this.validatorSelect.element.value);
		if(paar != null && paar[1] == this.mediator.config.dbTrue) {
			return this.validatorSelect.isVisible();
		}
		return false;
	}
	this.decorateFieldOld = FormFieldValidator_decorateField;
	this.decorateField = function (showEmptys) {
		if(this.isVisible()) {
			this.element.style.display = this.spWysw;
		} else {
			this.element.style.display = 'none';
		}
		this.decorateFieldOld(showEmptys);
	}
	
	/**
	 * ta metoda powinna byc wywolywana przez validatora select na zdarzenie onChange elementu select.
	 */
	this.onChange = function (selectValue) {
		var paarArr = getValuePaarArr(selectValue);
		if(paarArr && paarArr[1] == this.mediator.config.dbTrue) {
			// wyswietlanie pola dodatkowego
			this.element.style.display = this.spWysw;
			this.validate(false);
		} else {
			// ukrycie pola dodatkowego
			this.element.style.display = 'none';
		}
	}
}
DefSelectDescrFieldValidator.prototype = new DefFormFieldValidator();

function DefSelectDescrFieldValidatorP() {
	this.panelId = null;
	/*
	 * @param mediator
	 * @param elementId id opcjonalnego elementu opisowego.
	 * @param nazwaParametru nazwa parametru (opisowa).
	 * @param ZlecenieedSelectField validatorSelect obiekt validatora elementu select od ktorego wartosci zalezy wyswietlanie elementu opcjonalnego.
	 * @param spWysw sposob wyswietlania elementu opcjonalnego (inline/block). 
	 * @param panelId id panelu, na ktorym znajduje sie element zalezny od wyboru z listy select.
	 * @param string normalClass nazwa klasy CSS dla normalnego wyswietlania
	 * @param string errorClass nazwa klasy CSS dla wyswietlania w trybie error
	 */
	this.initDefSelectDescrFieldValidatorP = function (mediator, elementId, nazwaParametru, validatorSelect, spWysw, panelId, 
	normalClass, errorClass) {
		this.panelId = panelId;
		this.initDefSelectDescrFieldValidator(mediator, elementId, nazwaParametru, validatorSelect, spWysw, normalClass, errorClass);
	}
	this.decorateFieldOld = FormFieldValidator_decorateField;
	this.decorateField = function (showEmptys) {
		if(this.isVisible()) {
			document.getElementById(this.panelId).style.display = this.spWysw;
		} else {
			document.getElementById(this.panelId).style.display = 'none';
		}
		this.decorateFieldOld(showEmptys);
	}
	/**
	 * ta metoda powinna byc wywolywana przez validatora select na zdarzenie onChange elementu select.
	 */
	this.onChange = function (selectValue) {
		var paarArr = getValuePaarArr(selectValue);
		if(paarArr && paarArr[1] == this.mediator.config.dbTrue) {
			// wyswietlanie pola dodatkowego
			document.getElementById(this.panelId).style.display = this.spWysw;
			this.validate(false);
		} else {
			// ukrycie pola dodatkowego
			document.getElementById(this.panelId).style.display = 'none';
		}
	}
}
DefSelectDescrFieldValidatorP.prototype = new DefSelectDescrFieldValidator();


function DefCheckboxZSelectP() {
	this.isEmpty = function () {
		// w przypadku elementu typu checkbox pusta pusta wartosc oznacza niezaznaczenie wiec uznajemy ze checkbox
		// zawsze ma wartosc (true/false) i zwracamy zawsze false
		return false;
	}
	this.initDefCheckboxZSelectP = function (mediator, elementId, nazwaParametru, validatorSelect, spWysw, panelId, 
	normalClass, errorClass) {
		this.initDefSelectDescrFieldValidatorP(mediator, elementId, nazwaParametru, validatorSelect, spWysw, panelId, 
			normalClass, errorClass);
	}
}
DefCheckboxZSelectP.prototype = new DefSelectDescrFieldValidatorP();



function DefFormFieldValidator_isIntGr0() {
	return validate_isIntegerGr(this.element, 0, null);
}

function IntGr0FieldValidator() {
	this.initIntGr0FieldValidator = function (mediator, elementId, mode, nazwaParametru, normalClass, errorClass) {
		this.initDefFormFieldValidator(mediator, elementId, mode, DefFormFieldValidator_isIntGr0, nazwaParametru, 'onchange',
			normalClass, errorClass);
	}
}
IntGr0FieldValidator.prototype = new DefFormFieldValidator();





function DefFormFieldValidator_isIntGrE0() {
	return validate_isIntegerGrE(this.element, 0, null);
}

function IntGrE0FieldValidator() {
	this.initIntGrE0FieldValidator = function (mediator, elementId, mode, nazwaParametru, normalClass, errorClass) {
		this.initDefFormFieldValidator(mediator, elementId, mode, DefFormFieldValidator_isIntGrE0, nazwaParametru, 'onchange',
			normalClass, errorClass);
	}
}
IntGrE0FieldValidator.prototype = new DefFormFieldValidator();




function DefFormFieldValidator_isNumberGr0() {
	return validate_isNumberGrE(this.element, 0, null);
}

function NumberGr0FieldValidator() {
	this.initNumberGr0FieldValidator = function (mediator, elementId, mode, nazwaParametru, normalClass, errorClass) {
		this.initDefFormFieldValidator(mediator, elementId, mode, DefFormFieldValidator_isNumberGr0, nazwaParametru, 'onchange',
			normalClass, errorClass);
	}
}
NumberGr0FieldValidator.prototype = new DefFormFieldValidator();

