/** start: Constants **/
var CSS_ERROR = 'errInput';
var CSS_INACTIVE = 'inactive';
var MSG_ERROR = 'Some information are missing, please fill-in the hi-lighted field(s).'
/** end: Constants **/

/** start: Min/Max Values **/
var MinValue = {
	Int:-2147483648
};

var MaxValue = {

};

/** end: Min/Max Values **/

/** start: Array.prototype **/
Object.extend(Array.prototype, {
    findByProp: function(prop, val) {
        return this.find(function(el) {
            return el[prop] == val;
        })
    },

    addRange: function(items) {
        for (var i = 0; i < items.length; i++)
            this.push(items[i]);
    }
});

/** end:  Array.prototype **/

/** start: String.prototype **/
Object.extend(String.prototype,{
	trim: function(){
		var m =  this.match(/^\s*(\S+(\s+\S+)*)\s*$/);
		return m == null ? '' : m[1];
	},

	/**	
	 * Format a String with the passed Object.
	 * <p>Usage: 'format this #{prop1} and #{prop2}'. format({prop1:value1, prop2:value2});
	 * <br/>==> 'format this value1 and value2'</p>
	 * <p>'format this #{prop1} and #{prop2}'. format({prop1:value}, true);
	 * <br/>==> 'format this value1 and #{prop2}'</p>
	 * @alias String.prototype.format
	 * @see String.prototype.format2
	 * @method
	 * @param {object} pairs the Object whose properties to be used for format
	 * @param {bool} [keepXtras] whether to keep non-existance properties or not
	 * @return {String}
	 */
	format: function (obj, keepXtras){
		var s = this;
		for(var name in obj){
			var re = new RegExp('#\\{' + name + '\\}', 'g');
			s = s.replace(re, obj[name]);
		}
		if(!keepXtras) 
			s = s.replace(/#{([^\}\s]+)}/g, ''); 
		return s;
		
		
	},
	
	/**	
	 * Format a String with the passed arguments.
	 * <p>Usage: 'format this #{0} and #{1}'. format(value1, value2);</p>
	 * <br/> ==> 'format this value1 and value2'</p>
	 * @alias String.prototype.format2
	 * @see String.prototype.format.
	 * @method
	 * @param {...} pairs the Object whose properties to be used for format
	 * @return {String}
	 */
	format2: function(){
		var s = this; 
		for(var i=0;i<arguments.length;i++){
			var re = new RegExp('#\\{' + i + '\\}', 'g');
			s=s.replace(re,arguments[i]);
		}
		return s;
	},
	
	equal: function(str, caseSensitive){
		return caseSensitive ? this == str : this.toUpperCase() == str.toUpperCase();
	},
	
	toInt: function(radix){
		return parseInt(this, radix || 10);
	},
	toFloat: function(){
		return parseFloat(this);
	}
});
/** end: String.prototype **/

/** start: Date Prototypes **/
Date.prototype.format = function (){
	var d = this.getDate();
	var m = this.getMonth()+1;
	d = d<10 ? ('0'+d) : d;
	m = m<10 ? ('0'+m) : m;
	return d + '/' + m + '/' + this.getFullYear();	
}

/** end: Date Prototypes **/

/** start: Utilities functions **/

var $C = document.getElementsByClassName;

var $T = function(tag, par){
 return ($(par)||document).getElementsByTagName(tag);
}

var $O = function(id){
	return opener.document.getElementById(id);
}
var $OF = function(id){
	var v = $O(id).value;
	return v ? v.trim() : v;
}
if(_$F) alert('"util.js" is included multiple times and raised circular reference.\nRemove duplicate Script tags with src="util.js"');
var _$F = $F;
$F = function(e){
	var v = _$F(e);
	return v ? v.trim() : v;
}


/** end: Utilities functions **/

/** start: util **/
var util = {
	boolLabel: $w('No Yes'),
	error: null,
	popup: null,
	dialogArgs: null,
	retValue:null,
	modalEvents: $w('click mousemove keypress'),
	
	uniqId: function(){
		return util.uniqId._id = (util.uniqId._id || 0) - 1;
	},
	
	/**
	 * Checks if the string is empty.
	 * @param {string} s the string to check
	 * @return {bool}
	 */
	isEmpty: function(s){
		return ! ((s!=null) && /^\s*(\S+(\s+\S+)*)\s*$/.test(s));
	},
	
	hasInvailsChar: function (s, withSpace){
		return (withSpace) ? /[^a-zA-Z0-9 ]/g.test(s) :	/[^a-zA-Z0-9]/g.test(s);
	},

	isEmail: function (s){
		return  /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(s);
	},

	isDigit: function (s){
		return /^\s*\d+\s*$/.test(s);
	},
	isFloat: function (s){
		return /^\s*(\d+)?(\.(\d+))?\s*$/.test(s);
	},
	isMoney: function (s, withSymbol){
		if(withSymbol)
			return /^\s*([^\d]+)?(\d+)?(\.(\d{1,2}))?([^\d]+)?\s*$/.test(s);
		return /^\s*(\d+)?(\.(\d{1,2}))?\s*$/.test(s);
	},

	isDate: function(str, returnDate){
		//var regex = /^(\d{2})\/(\d{2})\/(\d{2}|\d{4})$/;
		var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
		if(! regex.test(str)) return returnDate ? null : false;
		var date = str.replace(regex, '$2/$1/$3')
		var dParts = date.split('/');

		var d = new Date(date);
		for(var i=0; i<dParts.length; i++) dParts[i] = parseInt(dParts[i], 10);
		var ok = ( dParts[0] == (1+d.getMonth()) ) && (dParts[1] == d.getDate()) && (dParts[2] == d.getFullYear());
		
		if(returnDate) // retrun the Date object instead boolean
			return ok ? d : null;
		
		return ok;
	},
	
	isNumericKey: function(event, isFloat){
		var key = event.keyCode || event.charCode;
				
		if(	event.keyCode && 
			!event.shiftKey && 
			(key > 95 && key < 106) ||
			(isFloat && (key==110 || key==190)))
			return true;
		
		if( (!event.shiftKey) && (
			(key > 47 && key < 58) || 
			(key > 36 && key < 41) ||
			(key == Event.KEY_BACKSPACE) ||
			(key == Event.KEY_TAB) ||
			(key == Event.KEY_RETURN)||
			(key == Event.KEY_DELETE) 
			))
			return true;
		
		Event.stop(event);
		return false;						
	},
	
	dateDiff: function(d1, d2){
		return Date.parseUK(d1) - (d2 ? Date.parseUK(d2) : Date.parseUK((new Date()).format()));
	},
	
	toCurrency: function(n){
		if(isNaN(+n)) n=0;
		n = (+n).toFixed(2).toString().split('.');
		return  n[0].toArray().reverse(true).join('').replace(/(\d{3})/g,'$1,')
				.toArray().reverse(true).join('').replace(/^(-)?,/,'$1')
				+ '.' + n[1];
	},
	
	setClass: function (id, cls){
		Element.addClassName(id, cls);
	},

	removeClass: function (id, cls){
		Element.removeClassName(id, cls);
	},

	alert: function(alertMsg){
		alertMsg ? alert(alertMsg) : alert(MSG_ERROR); 
	},
	
	stop: function (el, msg, event){
		el = $(el);
		msg = msg || ((el.title || el.id || '') + ' is required.');
		alert(msg);
		if(el.select)
			el.select();
		else
			el.focus();
		el.scrollTo();
		
		if(event)
			Event.stop(event);
		
	},

	setError: function(){
		var elems = arguments;
		for (var i=0; i<elems.length; i++)
			Element.addClassName($(elems[i]), CSS_ERROR);
	},
	
	clearError: function(){
		var elems = arguments;
		for (var i=0; i<elems.length; i++)
			Element.removeClassName($(elems[i]), CSS_ERROR);
	},	

	reset: function(){
		var elem;
		var elems = arguments;
		for (var i=0; i<elems.length; i++){
			elem = $(elems[i]);

			if(elem.type =='text'){
				elem.value = '';
				this.clearError(elem);
			}
			else if(elem.type == 'checkbox'){
				elem.checked=false;
			}
			else if(elem.type == 'select'){
				elem.selectedIndex=0;
				this.clearError(elem);
			}
		}
	},

	validateEmpty: function (){
	
		var isValid = true;
		var elems = arguments;
		var elem = null;
		for (var i=0; i<elems.length; i++)	{
			elem = $(elems[i]);
			
			if(this.isEmpty(elem.value)){
				this.setError(elem);
				isValid=false;
				this.error = this.error || elem;
			}
			else{
				this.clearError(elem);
			}
		}
			return isValid;
	},

	validateEmail: function (){
		var isValid = true;
		var elems = arguments;		
		var elem = null;
		for (var i=0; i<elems.length; i++){
			elem = $(elems[i]);
			if(! this.isEmpty( elem.value)){
				if(! this.isEmail(elem.value)){
					this.setError(elem);
					isValid=false;
					this.error = this.error || elem;
				}
				else{
					this.clearError(elem);
				}
			}
		}
		return isValid;
	},

	validateSelect: function (){
		var isValid = true;
		var elems = arguments;
		var elem = null;
		for (var i=0; i<elems.length; i++){
			elem = $(elems[i]);
			if(elem.options.length ==0){
				this.setError(elem);
				isValid=false;
				this.error = this.error || elem;

			}
			else{
				this.clearError(elem);
			}
		}
		return isValid;
	},

	validateNumber:  function (){
		var isValid = true;
		var elems = arguments;
		var elem = null;
		for (var i=0; i<elems.length; i++){
			elem = $(elems[i]);
			if(! this.isEmpty( elem.value))	{
				if(! this.isDigit(elem.value)){
					this.setError(elem);
					isValid=false;
					this.error = this.error || elem;
				}
				else{
					this.clearError(elem);
				}
			}
		}
		return isValid;
	},
	
	validateLength: function(){
		var isValid = true;
		var elems = arguments;
		var elem = null;
		for (var i=0; i<elems.length; i++){
			elem = $(elems[i].id);
			if(! this.isEmpty( elem.value)){
				if(elem.value.trim().length < elems[i].len)	{
					this.setError(elem);
					isValid=false;
					this.error = this.error || elem;
				}
				else{
					this.clearError(elem);
				}
			}
		}
		return isValid;
		
	},

	validateEquality: function (a, b){
		a = $(a);
		b = $(b);
		if(!(this.isEmpty(a.value) && this.isEmpty(b.value))){
			if(a.value != b.value){
				this.setError(a, b);
				return false;
			}
			else{
				this.clearError(a, b);
			}
		}
		return true;
	},
	
	clearForm:function(container){
	    Form.getElements(container).each(function(el){
	        if(/^(radio|checkbox)$/i.test(el.type))
                el.checked=false;
            else
                el.value = '';
	    });
	},
	
	toggleDisability: function(els, disabled){
		$A(els).each(function(el){
			var el = $(el);
			el.removeClassName('disabled');
			if(el.nodeName == 'A')
				util.toggleLink(el, disabled);
			else{
				el.disabled  = disabled;
				if(disabled && (el.nodeName == 'TEXTAREA' || el.type == 'text')){
					el.value = '';
					el.addClassName('disabled')
				}
			}
			
		});
	},
	
	convertToCss: function (obj){
		var css={};
		$H(obj).each(function(i){
				css['_' + i.key] = i.value ?  '' : 'hidden';
			});
		return css;
	},
	
	formatEmptyValues: function (obj){
		obj = $H(obj);
		obj.each(function(i){
				obj[i.key] = (util.isEmpty(i.value) ||  i.value==undefined) ?  '&nbsp;' : i.value;
			});
		return obj;
	},
	
	prepareDom: function(parent){
		$D = window.$D || {};
		$A($T('*', parent)).each(function(e){
			if(e.id){
				$D[e.id] = $(e.id);				
			}
		});
	},
	
	toggleLink: function(link, disabled, opacity){
		link = $(link);
		link.disabled  = disabled;
		link.xhref = link.getAttribute('href') || link.xhref;
		link.setStyle( {cursor: disabled ? 'default' : 'pointer',
						opacity: disabled ? (opacity || .5) : 1});
		disabled ? link.removeAttribute('href') : link.setAttribute('href', link.xhref);
	},
	
	toggleLinkBtn: function(btn, disabled){
		btn = $(btn);
		btn.disabled  = disabled;
		btn.style.cursor = disabled ? 'auto' : 'pointer';		
	},

	open: function(url, width, height, hasScroll, args,resizable){
		util.setDialogArgs(args);
		hasScroll = hasScroll || false;
		resizable = resizable || false;
	   
		util.popup = window.open(url, '', 'height=#{h}, width=#{w}, left=#{left}, top=#{top}, scrollbars=#{s},toolbar=no,menubar=no,location=no,resizable=#{r}'
					.format({h:height, w:width, s:+hasScroll,r:+resizable, 
					left:(screen.availWidth-width)/2, 
					top:(screen.availHeight-height)/2}));
		
		if(util.popup)
			util.modalEvents.each(function(e){
				Event.observe(document.body, e , util._modalBlock);
			});
		else
			util.modalEvents.each(function(e){
				Event.stopObserving(document.body, e , util._modalBlock);
			});
	},	
	_modalBlock: function(){
		try{
			if (util.popup && util.popup.document)
				util.popup.focus();
			else
				util.modalEvents.each(function(e){
					Event.stopObserving(document.body, e , util._modalBlock);
				});
		}
		catch(ex) { }
	},
		
	close: function(ret){
		if(ret && ret.isReload)
			util.reload();
		else if(ret && ret.onclose){
			if(opener)
				ret.onclose(ret);
		}
		close();
	},
	
	reload: function(){
		if(opener)
			opener.location.reload(true);
	},	
	
	getDialogArgs: function(){
		try{
			if(opener)
				return opener.util.dialogArgs;
		}catch(e){}
	},
	
	setDialogArgs: function(o){
		util.dialogArgs = o;
	},
	
	getRetValue: function(){
		return util.retValue;
	},
	
	setRetValue: function(o){
		if(opener)
		 opener.util.retValue = o;
	},

	createSortables: function(id, data, seqField, emptyText, getHTML, onUpdateDone){
		
		var tbody = data.inject([], getHTML);
		
		
		if(!tbody.length){
			$(id).update(emptyText || '');
			return;
		}
		
		$(id).update(tbody.join(''));
		Sortable.create(id, {tag:'tr', treeTag:'tbody',starteffect:Prototype.K,
			onUpdate: function() {
				
				Sortable.sequence(id).each(function(seq, ind){
					data[+seq][seqField] = ind;
				});
				
				data = data.sortBy(function(f){return f[seqField];});
				onUpdateDone(data);
				
				util.createSortables(id, data, seqField, emptyText, getHTML, onUpdateDone);

			} 
		});
	},
	
	_getModalOpts: function(opts){
		return Object.extend({
			effect: 'BlindDown',
			duration: 0.3,
			center:true,
			overlay:'__overlay__',
			transition: Effect.Transitions.EaseFromTo,
			beforeStart: Prototype.emptyFunction,
			afterFinish: Prototype.emptyFunction
		},opts);
	},
	
	showModal: function(div, opts){
		opts = util._getModalOpts(opts);
		
		var win = document.viewport.getDimensions(),
			scrl = document.viewport.getScrollOffsets(),
			width = win.width + scrl[0],
			height = win.height + scrl[1];
			
		if(opts.center){
			var el = $(div).getDimensions(),
				left = (win.width - el.width)/2 + scrl[0],
				top = (win.height - el.height)/2 + scrl[1];
			
			left = left<=0 ? 0 : left;
			top = top<=0 ? 0 : top;
			$(div).setStyle('left:#{0}px; top:#{1}px;'.format2(left, top));
		}
		
		var overlay = $(opts.overlay);
		if(!overlay){
			overlay = new Element('iframe', {id: opts.overlay, frameborder:0, scrolling:"no"})
					.setStyle('position:absolute;top:0;left:0;opacity:0;z-index:997;width:100%;height:100%');
			$$('body')[0].insert(overlay);
		}
		
		$(div).visualEffect(opts.effect, {
				duration:opts.duration, 
				beforeStart:opts.beforeStart,
				transition: opts.transition,
				afterFinish:function(){
					overlay.show();
					opts.afterFinish();
				}
			});
	},
	
	hideModal: function(div, opts){
		opts = util._getModalOpts(opts);
		opts.effect ='Fade';
		opts.duration = 0.2;

		$(div).visualEffect(opts.effect, {
				duration:opts.duration, 
				afterFinish:opts.afterFinish,  
				beforeStart:function(){
					$(opts.overlay).hide();
					opts.beforeStart();
				}
			});
	},
	
	getBaseUrl: function(){
		var url = $$('script[src$="/util.js"]')[0].src.toLowerCase().replace('javascript/jslibs/util.js', '');
		util.getBaseUrl = function(){return url;};
		return url;
	},
	
	bindMaxLength: function(txt){
		var checkLen = function(event){
			var key = event.keyCode || event.charCode;
			if( 
				(key == Event.KEY_BACKSPACE) ||
				(key == Event.KEY_TAB) ||
				(key == Event.KEY_RETURN)||
				(key == Event.KEY_DELETE) 
			  )
				return true;
			
			var maxLength = +this.getAttribute('maxlength');	
			if(maxLength <= this.value.length){
				event.stop();
				return false;
			}
			return true;
		};
		
		var truncateLen = function(event){
			var maxLength = +this.getAttribute('maxlength');	
			if(maxLength <= this.value.length){
				this.value = this.value.substring(0, maxLength);
			}
		};
		
		txt = $(txt);
		txt.observe('keypress', checkLen);
		txt.observe('change', truncateLen);
		txt.observe('blur', truncateLen);
	}
};

/** end: util **/

Date.parseUK = function (str){
	return util.isDate(str, true);
}

Date.evalJSON = function(str){
	return new Date(str.replace(/-/gi, '/').replace('T', ' '));
}

Event.observe(window, 'unload', function(){
	try{
		if(window.opener && window.opener.util && window.opener.util.popup){
			window.opener.util.popup=null;
			util.modalEvents.each(function(e){
				Event.stopObserving(window.opener.document.body, e , window.opener.util._modalBlock);
			});
		}
		
		if(window && window.util && window.util.popup){
			window.util.popup.close();
		}
	}catch(e){};
});


Event.onReady(function(){
	$$('textarea[maxlength]').each(function(txt){
		util.bindMaxLength(txt);
	});
});

