/**
 * Shortcut function to document.getElementById(.)
 * Such solution costs less bytes of transfer and is quicker to write.
 *
 * @param string id
 */
function $() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string')
			element = document.getElementById(element);
		if (arguments.length == 1)
			return element;
		elements.push(element);
	}
	return elements;
};

function time()
{
	return (new Date()).getTime();
};

/**
 * Removes white space characters from the beginning and the end of a string
 * 
 * @param string string to trim
 * @param string chars the characters to remove (optional)
 * @return string
 */
function trim(str, chars) {
    return ltrim(rtrim(str, chars), chars);
};

/**
 * Removes white space characters from the beginning of a string
 * 
 * @param string string to trim
 * @param string chars the characters to remove (optional)
 * @return string
 */
function ltrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
};

/**
 * Removes white space characters from the end of a string
 * 
 * @param string string to trim
 * @param string chars the characters to remove (optional)
 * @return string
 */
function rtrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
};

/**
 * <class>
 * Allows to handle events as in normal Listener pattern
 * You can add these listeners using eventHandler.
 * Please notice that this will be the obj object (prolly owner of func)
 * Function takes three parameters: event, caller and listener.
 * Usually the event is the parameter sent via builtin browser engine and
 * caller is accessible as this. Here this is the specified object.
 * listener is the listener object itself.
 *
 * @param object obj the object that will be accessible as this
 * @param Function func the function that will be run.
 */
function Listener(obj,func)
{
	if (typeof(obj) != 'object')
		throw new Error("Supplied parameter 1 '"+obj+"' is not an object");
	this.obj = obj;
	
	if (!(func instanceof Function))
		throw new Error("Supplied parameter 2 '"+func+"' is not a function");
	this.func = func;
	
	this.onEvent = function(event,caller)
	{
		return this.func.call(this.obj,event,caller,this);
	}
};

/**
 * Use this to inform listeners. First parameter can be listener object or function.
 * if it is a function the event will be handled in normal (common known) way.
 * 
 * @param mixed lis listener object of function
 * @param Event event the event object
 * @param object caller the caller object
 */
function informListener(lis,event,caller)
{
//	if( lis instanceof Listener )
	if ( typeof(lis) == 'object' )
		return lis.onEvent(event,caller);
	else
		return lis.call(caller,event);
}

var NEXT_UNIQUE_ID = time();

/**
 * Cross browser event handling
 */
var eventHandler =
{
	evtHash: [],

	ieGetUniqueID: function(_elem)
	{
		if (_elem.eventHandlerUniqueID) return _elem.eventHandlerUniqueID;
		else { _elem.eventHandlerUniqueID = NEXT_UNIQUE_ID++; return _elem.eventHandlerUniqueID; }
	},
   
	addListener: function(_elem, _evtName, _fn, _useCapture)
	{
		var f; var af; var lisId = eventHandler.ieGetUniqueID(document);
		if (!_elem)
			throw new Error("Given object to be listened is null!");
		if (_fn instanceof Listener) //listener like handling
		{
			f = function(event) {
				if (event.srcElement)
					try {event.target = event.srcElement; } catch(e) {}
				informListener(_fn,event,_elem);
			};
			lisId = eventHandler.ieGetUniqueID(_fn);
			af = _fn.func;
		}
		else 
		{
			f = _fn;
			af = _fn;
		}
		var key = '{FNKEY::obj_' + eventHandler.ieGetUniqueID(_elem) + '_' + lisId +
				'::evt_' + _evtName + '::fn_' + af + '}';
		if (typeof _elem.addEventListener != 'undefined')
		{ 
			_elem.addEventListener(_evtName, f, _useCapture); 
		}
		else if (typeof _elem.attachEvent != 'undefined')
		{
			var ef = eventHandler.evtHash[key];
			if (typeof ef != 'undefined') return;
			if (!(_fn instanceof Listener)) //listener like handling
			{
				f = function(event) {
					if (event.srcElement)
					{
						try {
							event.target = event.srcElement;
						} catch(e) {}
					}
					_fn.call(_elem,event);
				};
			}
			_elem.attachEvent('on' + _evtName, f);

			// attach unload event to the window to clean up possibly IE memory leaks
			window.attachEvent('onunload', function()
			{
				_elem.detachEvent('on' + _evtName, f);
			});
         
			//f = null;   /* DON'T null this out, or we won't be able to detach it */
		}
		else
		{ 
			_elem['on' + _evtName] = f;
		}
		eventHandler.evtHash[key] = f;
		key = null;
	},

	removeListener: function(_elem, _evtName, _fn, _useCapture)
	{
		var af; var lisId = eventHandler.ieGetUniqueID(document);
		if (_fn instanceof Listener) //listener like handling
		{
			af = _fn.func;
			lisId = eventHandler.ieGetUniqueID(_fn);
		}
		else 
			af = _fn;
		var key = '{FNKEY::obj_' + eventHandler.ieGetUniqueID(_elem) + '_' + lisId +
					'::evt_' + _evtName + '::fn_' + af + '}';
		var f = eventHandler.evtHash[key];
		if (typeof _elem.removeEventListener != 'undefined')
		{
			if (typeof f != 'undefined')
				_elem.removeEventListener(_evtName, f, _useCapture);
		}
		else if (typeof _elem.detachEvent != 'undefined')
		{
			if (typeof f != 'undefined')
				_elem.detachEvent('on' + _evtName, f);
         	//f = null;   /* DON'T null this out, or we won't be able to detach it */
		}
		delete eventHandler.evtHash[key];
		key = null;
	},

	cancelEvent: function(e)
	{
		if(e.stopPropagation)
			e.stopPropagation();
		if(e.preventDefault)
			e.preventDefault();
		e.cancelBubble = true;
		e.cancel = true;
		e.returnValue = false;
		return false;
	}
};

var OK_IMG_ADDR = 'img/ok.png';
var ERR_IMG_ADDR = 'img/err.png';


//preload
var img = document.createElement('img');
img.src = OK_IMG_ADDR;
img = document.createElement('img');
img.src = ERR_IMG_ADDR;

/**
 * <class>
 * Checks if fields are filled correctly.
 */
function AccidentForm() {
	/**
	 * <constructor>
	 */
	this.init = function() {
		this.dom = document.getElementsByTagName('form');
		this.dom = this.dom[0];
		this.dom.controller = this;
		
		this.ica = new Array();
		this.registerChecks(); //register check code to fields
		
		eventHandler.addListener(this.dom,'submit',new Listener(this,this.onSubmit));
	};
	
	/**
	 * Add code that checks if fields are filled correctly.
	 */
	this.registerChecks = function() {
		var ic, i;
		
		i = this.getInput('name');
		ic = new InputCheck(i);
		ic.addCheck(new LengthCheck(3,i.maxLength));
		this.ica.push(ic);
		
		i = this.getInput('email');
		ic = new InputCheck(i);
		ic.addCheck(new EmailCheck());
		ic.addCheck(new LengthCheck(0,i.maxLength))
		ic.addCheckOn('keyup');
		this.ica.push(ic);
		
		i = this.getInput('telefon');
		ic = new InputCheck(i);
		ic.addCheck(new LengthCheck(0,i.maxLength));
		ic.addCheck(new PhoneCheck());
		this.ica.push(ic);
		
		i = this.getInput('street');
		ic = new InputCheck(i);
		ic.addCheck(new LengthCheck(0,i.maxLength));
		this.ica.push(ic);
		
		ic.es.enableIco(false);
		//move message divs to front
		ic.td.insertBefore(ic.lenMsg,ic.td.firstChild);
		ic.td.insertBefore(ic.es.errMsgDiv,ic.lenMsg);
		
		this.ica.push(ic);
	};
	
	this.onSubmit = function(ev) {
		if (this.finalCheck()) return;
		eventHandler.cancelEvent(ev);
		alert('Formularz został wypełniony błędnie.');
	};
	
	this.finalCheck = function() {
		var flag = true;
		for (var i = 0 ; i < this.ica.length ; ++i)
		{
			flag = this.ica[i].finalCheck() && flag;
		}
		return flag;
	};
	
	this.getInput = function(name) {
		for (var i = 0 ; i < this.dom.elements.length ; ++i)
			if (this.dom.elements[i].name == name) return this.dom.elements[i];
		return null;
	};
	
	this.init();
};

/**
 * <class>
 * Checks if field is correct. Displays error message.
 */
function InputCheck(input) {
	
	/**
	 * <constructor>
	 */
	this.init = function(input) {
		this.checks = new Array();
		this.err = new Array();
		this.checkOn = new Array();
		this.input = input;
		
		this.td = this.input.parentNode;
		
		this.allowEmpty = true;
		//try to find out if is required
		if (this.td.cellIndex > 0 &&
			this.td.parentNode.cells[this.td.cellIndex - 1].innerHTML.search('[*]') != -1)
			this.allowEmpty = false;
		
		this.es = new ErrShower(input);
		
		eventHandler.addListener(this.input,'focus',new Listener(this,this.onFocusContext));
		eventHandler.addListener(this.input,'blur',new Listener(this,this.onBlurContext));
		this.addCheckOn('blur');
	};
	
	this.addCheckOn = function(evtName) {
		for (var i = 0 ; i < this.checkOn.length ; ++i)
		{
			if (this.checkOn[i] == evtName) return;
		}
		this.checkOn.push(evtName);
		eventHandler.addListener(this.input,evtName,this.onCheckLis);
	};
	
	this.onCheck = function() {
		this.check();
	};
	this.onCheckLis = new Listener(this,this.onCheck);
	
	this.onFocusContext = function() {this.onFocus();};
	this.onFocus = function() {
		if (this.err.length > 0) //already has errors
			this.addCheckOn('keyup');
	};
	
	this.onBlurContext = function() {this.onBlur();};
	this.onBlur = function() {
		this.input.value = trim(this.getValue());
		this.addCheckOn('keyup');
	};
	
	this.getValue = function() {
		return this.input.value;
	};
	
	this.addCheck = function(c) {
		this.checks.push(c);
	};
	
	this.check = function() {
		var res = this.checkOnly();
		this.showErr(!res);
		return res;
	};
	
	this.checkOnly = function() {
		var flag = true;
		this.err = new Array();
		if (trim(this.getValue()).length == 0) //empty
		{
			if (this.allowEmpty) return true;
			this.err.push('Wypełnij obowiązkowe pole.');
			return false;
		}
		for (var i = 0 ; i < this.checks.length ; ++i)
		{
			if (!this.checks[i].check(this.input)) {
				flag = false;
				this.err.push(this.checks[i].error);
			}
		}
		return flag;
	};
	
	this.showErr = function(yes) {
		if (!yes)
		{
			if (trim(this.getValue()).length == 0 && this.allowEmpty)
				this.es.showNone();
			else
				this.es.showOK();
		}
		else
		{
			this.es.showErrMsg(this.err);	
		}
	};
	
	this.finalCheck = function() {
		this.es.enableFinalMode();
		return this.check();
	};
	
	this.init(input);
};

function SelectCheck(input) {
	var t = new InputCheck(input);
	
	t.init = function(input) {
		eventHandler.addListener(input,'change',new Listener(this,this.onSelect));
	};
	
	t.getValue = function() {
		var v = this.input.options[this.input.selectedIndex].value;
		if (v == '0')
			v = '';
		return v;
	};
	
	t.onBlur = function() {};
	t.onSelect = function() {
		this.check();
	}; 
	t.init(input);
	return t;
};

function ErrShower(input) {
	this.finalMode = false;
	
	this.init = function(input) {
		this.input = input;
		
		this.td = this.input.parentNode;
		this.inpDiv = document.createElement('div');
		this.errIcoDiv = document.createElement('div');
		this.errMsgDiv = document.createElement('div');
		
		var d = document.createElement('div');
		d.style.overflow = 'hidden';
		d.style.width = '100%';
		this.td.appendChild(d);
		d.appendChild(this.inpDiv);
		d.appendChild(this.errIcoDiv);
		
		this.td.appendChild(this.errMsgDiv);
		
		this.inpDiv.appendChild(this.input);
		
		this.inpDiv.style.width = '';
		this.inpDiv.style.cssFloat = 'left';
		this.inpDiv.style.styleFloat = 'left';
		
		this.errIcoDiv.className = 'err';
		this.errIcoDiv.style.width = '16px';
		this.errIcoDiv.style.paddingLeft = '2px';
		this.errIcoDiv.style.cssFloat = 'left';
		this.errIcoDiv.style.styleFloat = 'left';
		this.errIcoDiv.style.height = '16px';
		this.errIcoDiv.style.overflow = 'hidden';
		
		this.errMsgDiv.className = 'errMsg';
		this.errMsgDiv.style.display = 'none';
	};
	
	this.showErrMsg = function(err) {
		if (!(err instanceof Array)) err = new Array(err);
		this.errIcoDiv.innerHTML = '';
		this.errMsgDiv.style.display = 'block';
		
		var img;
		if (!this.finalMode)
		{
			img = document.createElement('img');
			img.src = ERR_IMG_ADDR;
			img.alt = 'błąd';
			this.errIcoDiv.appendChild(img);
		}
		var et = '';
		for (var i = 0 ; i < err.length; ++i)
			et += err[i]+'<br/>';
		this.errMsgDiv.style.color = (this.finalMode) ? '#fff' : '#f00';
		this.td.bgColor = (this.finalMode) ? '#ff0000' : '#eeeeee';
		this.errMsgDiv.innerHTML = et;
		this.errMsgDiv.style.display = 'block';
	};
	
	this.showOK = function() {
		this.finalMode = false;
		this.errIcoDiv.innerHTML = '';
		this.errMsgDiv.innerHTML = '';
		this.errMsgDiv.style.display = 'none';
		this.td.bgColor = '#eeeeee';
		this.td.style.color = '#5A5A5A';
		var img = document.createElement('img');
		img.src = OK_IMG_ADDR;
		img.alt = '';
		img.title = 'pole wypełnione poprawnie';
		this.errMsgDiv.innerHTML = '';
		this.errIcoDiv.appendChild(img);
	};
	
	this.showNone = function() {
		this.finalMode = false;
		this.errMsgDiv.innerHTML = '';
		this.errIcoDiv.innerHTML = '';
		this.errMsgDiv.style.display = 'none';
		this.td.bgColor = '#eeeeee';
	};
	
	this.enableIco = function(yes) {
		this.useIco = yes;
		this.errIcoDiv.style.display = (yes) ? 'block' : 'none'; 
	}
	
	this.enableFinalMode = function() {
		this.finalMode = true;
		this.errIcoDiv.innerHTML = '';
	};
	
	this.init(input);
};

function TextareaCheck(input,maxLen) {
	var t = new InputCheck(input);

	t.init = function(input,maxLen) {
		this.maxLength = maxLen;
		
		this.lenMsg = document.createElement('div');
		this.lenMsg.style.textAlign = 'right';
		this.es.inpDiv.appendChild(this.lenMsg);
		
		eventHandler.addListener(this.input,'keyup',new Listener(this,this.checkLength));
		
		this.updateLenMsg();
	};
	
	t.checkLength = function() {
		var v = trim(this.getValue());
		if (v.length > this.maxLength)
		{
			this.input.value = v.substr(0,this.maxLength);
		}
		this.updateLenMsg();
	};
	
	
	
	t.updateLenMsg = function() {
		var v = this.input.value;
		this.lenMsg.innerHTML = 'wykorzystane znaki: '+v.length+'/'+this.maxLength;
		this.boldLenMsg(v.length >= this.maxLength);
	};
	
	t.boldLenMsg = function(yes) {
		if (yes)
		{
			this.lenMsg.style.color = '#f00';
			this.lenMsg.style.fontWeight = 'bold';
		}
		else
		{
			this.lenMsg.style.color = '#5A5A5A';
			this.lenMsg.style.fontWeight = 'normal';
		}
	};
	
	t.init(input,maxLen);
	return t;
};

/**
 * Checks if length is correct.
 */
function LengthCheck(min,max) {
	this.min = min;
	this.max = parseInt(max);
	if (isNaN(this.max) || this.max <= 0)
		throw 'Podany drugi parametr \''+max+'\' nie jest liczbą dodatnią';
	
	this.error = '';
	
	this.check = function(input) {
		this.error = '';
		var v = trim(input.value);
		if (v.length > this.max)
		{
			this.error = 'Pole może zawierać maksymalnie <b>'+this.max+'</b> znaków (zawiera '+v.length+')';
			return false;
		}
		else if (v.length < this.min)
		{
			if (this.min == 1) c
			this.error = 'Pole musi zawierać przynajmniej '+this.min+' znaków'; 
			return false;
		}
		return true;
	};
};

function PhoneCheck() {
	
	this.error = '';
		
	this.check = function(input) {
		this.error = '';
		var v = input.value;
		v = v.replace(/\D/g,'');
		if (v.length < 9)
		{
			this.error = 'Wprowadź poprawny numer telefonu.';
			return false;
		}
		return true;
	};
};

/**
 * Checks if field contains email.
 */
function EmailCheck() {
	
	this.error = '';
		
	this.check = function(input) {
		this.error = '';
		var v = input.value;
		if (-1 == v.search(/^[a-z0-9_\-\.]+@([a-z0-9_\-]+\.)+[a-z]{2,4}$/i))
		{
			this.error = 'Wprowadź poprawny adres e-mail.';
			return false;
		}
		return true;
	};
};

function PeselCheck() {
	
	this.error = '';

	this.check = function(input) {
		this.error = '';
		var v = trim(input.value);
		if (v.search(/^\d+$/) == -1 || v.length != 11)
		{
			this.error = 'Wprowadź prawidłowy numer PESEL.';
			return false;
		}
		return true;
	};
};

function DowodCheck() {
	this.error = '';

	this.check = function(input) {
		this.error = '';
		var v = trim(input.value);
		if (v.search(/^[A-Z]{2,4} ?\d{5,7}$/i) == -1)
		{
			this.error = 'Wprowadź poprawny numer dowodu.';
			return false;
		}
		else
		{
			input.value = v.replace(' ','');
		}
		return true;
	};
};

function CodeCheck() {
	this.error = '';

	this.check = function(input) {
		this.error = '';
		var v = trim(input.value);
		if (v.search(/^\d\d-\d\d\d$/) == -1)
		{
			this.error = 'Wprowadź poprawny kod pocztowy (przykład: 12-345)';
			return false;
		}
		else
		{
			input.value = v.replace(' ','');
		}
		return true;
	};
};

eventHandler.addListener(window,'load',function() {new AccidentForm();});








