
/**
* Alguns mtodos destas classes foram baseados nos m�todos do YUI,
* com melhoras e atualizaes.
*/

if (typeof ICore == 'undefined') {
	ICore = { };
}

/**
 * Se a p�gina j� carregou.
 */
ICore.pageLoaded = false;

/**
 * M�todo que trata de herdar uma classe da outra
 * @param {Function} subc
 * @param {Function} superc
 * @param {Object} overrides
 */
ICore.extend = function(subc, superc, overrides) {
	if (!superc||!subc) {
		throw new Error("Erro, classes n�o definidas.");
	}
	var F = function() {};
	F.prototype=superc.prototype;
	subc.prototype=new F();
	subc.prototype.constructor=subc;
	subc.superclass=superc.prototype;
	if (superc.prototype.constructor == Object.prototype.constructor) {
		superc.prototype.constructor=superc;
	}

	if (overrides) {
		for (var i in overrides) {
			subc.prototype[i]=overrides[i];
		}
		if (ICore.nav.isIE) {
			var add=["toString", "valueOf"];
			for (i=0;i<add.length;i=i+1) {
				var fname=add[i],f=overrides[fname];
				if (ICore.util.isFunction(f) && f!=Object.prototype[fname]) {
					subc.prototype[fname]=f;
				}
			}
		}
	}
};

/**
 * Objeto que trata a de diferenciar os navegadores.
 * @type {Object}
 */
ICore.nav = {
	isIE: (navigator.userAgent.indexOf('MSIE') > -1),
	isIE55: (navigator.userAgent.indexOf('MSIE 5.5') > -1),
	isIE6: (navigator.userAgent.indexOf('MSIE 6') > -1),
	isFF: (navigator.userAgent.indexOf('Firefox') > -1),
	isOpera: (navigator.userAgent.indexOf('Opera') > -1)
};

/**
 * Constantes com os eventos.
 * 
 * @type {Object}
 * @memberOf ICore
 */
ICore.events = {
	LOAD: 'load',
	UNLOAD: 'unload',
	CLICK: 'click',
	DBLCLICK: 'dblclick',
	MOUSEDOWN: 'mousedown',
	MOUSEUP: 'mouseup',
	MOUSEWHEEL: 'mousewheel',
	MOUSEMOVE: 'mousemove',
	MOUSEOVER: 'mouseover',
	MOUSEOUT: 'mouseout',
	KEYDOWN: 'keydown',
	KEYUP: 'keyup',
	KEYPRESS: 'keypress',
	MOUSEWHEEL: (!ICore.nav.isFF)?'mousewheel':'DOMMouseScroll',
	SCROLL: 'scroll'
};

/**
 * Cole��o de exe��es do sistema.
 */
ICore.exceptions = {
	abort: function () { }
};

/**
 * Objeto que trata da intera��o e implementa��o de opera��es com os elementos.
 * 
 * @type {Object}
 * @memberOf ICore
 */
ICore.dom = {
	/**
	* Faz uma busca no documento por um elemento com o ID informado.
	*
	* @param {String} id ID que ser buscado.
	* @memberOf ICore.dom
	*/
	get: function (id) {
		return document.getElementById(id);
	},

	/**
	* Faz uma busca no documento por um elemento com a TagName igual
	* ao parametro passado.
	*
	* Retorna um array de HTMLElement.
	*
	* @param {String} tagname
	* @return {HTMLElement[]}
	* @memberOf ICore.dom
	*/
	getByTag: function (tagname, parent) {
		if (!parent) {
			parent = document;
		}
		return parent.getElementsByTagName(tagname);
	},

	/**
	* Faz uma busca no documento por um elemento que
	* contenha a classe informada no parametro em sua
	* lista.
	*
	* Retorna uma lista de HTMLElement.
	*
	* @param {String} classname
	* @param {HTMLElement} parent Nó onde deve ser procurado
	* @param {Boolean} indepth Buscar em todo o galho ou apenas neste nó.
	* @return {HTMLElemet[]}
	* @memberOf ICore.dom
	*/
	getByClass: function (classname, parent, indepth) {
		if (ICore.util.isUndefined(parent)) {
			parent = document;
		}
		var me = this;
		return this.findChild(parent, function (el) {
			return me.findClassName(classname, el);
		}, indepth);
	},

	/**
	* Cria um elemento.
	*
	* @param {String} tname
	* @return {HTMLElement}
	* @memberOf ICore.dom
	*/
	createEl: function (tagname) {
		return document.createElement(tagname);
	},

	/**
	* Adiciona uma elemento dentro de outro criado.
	*
	* @param {HTMLElement} el Elemento pai no qual o parametro child deve ser inserido.
	* @param {HTMLElement} child Filho que ser inserido.
	* @return {HTMLElement}
	* @memberOf ICore.dom
	*/
	appendChild: function (el, child) {
		return el.appendChild(child);
	},
	
	/**
	 * @param {HTMLElement} el
	 * @param {HTMLElement} child
	 * @param {HTMLElement} childBefore
	 */
	insertChildBefore: function (el, child, childBefore) {
		el.insertBefore(child, childBefore);
	},
	
	/**
	 * @param {HTMLElement} el
	 * @param {HTMLElement} child
	 */
	insertChildFirst: function (el, child) {
		el.insertBefore(child, el.firstChild);
	},

	/**
	* Cria um elemento de texto e o insere no objeto.
	*
	* @param {HTMLElement} el
	* @param {String} text
	* @memberOf ICore.dom
	*/
	appendText: function (el, text) {
		var child = document.createTextNode(text);
		return this.appendChild(child);
	},

	/**
	* Remove um elemento dentro de outro.
	*
	* @param {HTMLElement} el Elemento pai.
	* @param {HTMLElement} child Elemento que ser removido.
	* @return {HTMLElement}
	* @memberOf ICore.dom
	*/
	removeChild: function (el, child) {
		return el.removeChild(child);
	},

	/**
	* Altera a opacidade de um elemento.
	*
	* @param {HTMLElement} el
	* @param {Float} opacity Valor entre 0 (zero) e 1 (um).
	* @memberOf ICore.dom
	*/
	setOpacity: function (el, opacity) {
		if (ICore.nav.isIE) { // IE First by more navigators
			el.style.filter = 'filter:alpha(opacity='+(opacity*100)+')';
		} else if (ICore.nav.isFF) {
			el.style.mozOpacity = opacity;
		} else {
			el.style.opacity = opacity;
		}
	},

	/**
	* Esta classe verifica se uma classe (do css) est� aplicada a um
	* elemento.
	*
	* @param {String} classname
	* @param {String} classes
	* @return {Integer}
	* @memberOf ICore.dom
	*/
	findClassName: function (classname, classes) {
		if (typeof classes != 'string') {
			classes = classes.className;
		}
		if (classes) {
			var c = classes.split(' ');
			return (c.indexOf(classname) > -1);
		} else {
			return false;
		}
	},

	/**
	* Adiciona uma classe na lista de classes de um objeto.
	*
	* @param {HTMLObject} obj
	* @param {String} class
	* @memberOf ICore.dom
	*/
	addClass: function (obj, c) {
		var cls;
		if (obj.className) {
			cls = obj.className.split(' ');
		} else {
			cls = [];
		}
		if (cls.indexOf(c) == -1) {
			obj.className = obj.className + (obj.className === ''?'':' ') + c;
		}
	},

	/**
	* Remove uma classe na lista de classes de um objeto.
	*
	* @param {HTMLObject} obj
	* @param {String} class
	* @memberOf ICore.dom
	*/
	removeClass: function (obj, c) {
		var cls = obj.className.split(' ');
		var i = cls.indexOf(c);
		if (i > -1) {
			cls.splice(i, 1);
			obj.className = cls.join(' ');
		}
	},
	
	/**
	 * Lista de fun��es listeners de eventos.
	 * 
	 * @type {Array}
	* @memberOf ICore.dom
	 */
	listeners: [],
	
	/**
	 * Busca no array {ICore.dom.listeners} se um elemento j� est� inserido. 
	 * 
	 * @param {HTMLElement} el Elemento ao qual o evento ser� adicionado
	 * @param {String} event Evento que ser� adicionado
	 * @param {Function} fnc Fun��o que ser� chamada
	 * @param {Object} obj Objeto que ser� o "this" na fun��o chamada.
	 * @memberOf ICore.dom
	 */
	findListener: function (el, event, fnc, obj) {
		var l;
		for (var i = 0; i < this.listeners.length; i++) {
			l = this.listeners[i];
			if ((l.el == el) && (event == l.event) && (fnc == l.fnc) && (obj == l.obj)) {
				return i;
			}
		}
		return -1;
	},

	/**
	* Adicionar a fun��o para ser chamada quando o evento for disparado.
	*
	* @param {HTMLElement} el
	* @param {String} event
	* @param {Function} fnc
	* @param {obj} obj Objeto que ser� o "this" na fun��o chamada, caso n�o especificado ser� o proprio el
	* @memberOf ICore.dom
	*/
	addListener: function (el, event, fnc, obj) {
		el = ICore.util.object(el);
		if (obj) {
			wfnc = function (e) {
				e = e || event; // Fix para algum problema de vers�o do IE.
				fnc.call(obj, e);
			};
			this.listeners.push({el:el, event:event, fnc:fnc, obj:obj, wfnc: wfnc});
			this.addListener(el, event, wfnc);
		} else {
			if (el) {
				if (el.attachEvent) { // Pelo o IE ser mais usado;
					el.attachEvent('on' + event, fnc);
				} else {
					el.addEventListener(event, fnc, false);
				}
			} else {
				throw new Error('Objeto n�o encontrado.');
			}
		}
	},

	/**
	* Remove a fun��o da lista de chamadas quando o evento for disparado.
	*
	* @param {HTMLElement} el
	* @param {String} event
	* @param {Function} fnc
	* @memberOf ICore.dom
	*/
	removeListener: function (el, event, fnc, obj) {
		if (typeof el == "string") {
			el = this.get(el);
		}
		if (obj) {
			var i = this.findListener(el, event, fnc, obj);
			if (i > -1) {
				this.removeListener(el, event, this.listeners[i].wfnc);
				delete this.listeners[i].wfnc;
				delete this.listeners[i];
				this.listeners.deleteItem(i);
			}
		} else {
			if (el) {
				if (el.attachEvent) { // Pelo o IE ser mais usado;
					el.detachEvent('on' + event, fnc);
				} else {
					el.removeEventListener(event, fnc, false);
				}
			} else {
				throw new Error('Objeto não encontrado.');
			}
		}
	},

	/**
	* Faz um loop buscando entre os "pais" do elemento.
	* Ele chama uma fun��o, passada por parametro, para avaliar
	* a busca, e ao encontrar e retorna a refer�ncia do objeto
	* encontrado.
	*
	* @param {HTMLElement} el
	* @param {Function} fnc
	* @return {HTMLElement}
	* @memberOf ICore.dom
	*/
	findParent: function (el, fnc) {
		while (el.parentNode && !(fnc(el.parentNode))) {
			el = el.parentNode;
		}
		return el.parentNode;
	},

	/**
	* Faz um loop buscando entre os "filhos" do element.
	* Ela chama uma função, passada por parametro, para avaliar
	* a busca e ao finalizar retorna um array com os elementos
	* encontrados.
	*
	* @param {HTMLElement} el
	* @param {Function} fnc
	* @param {Boolean} indepth Analizar apenas estes nós ou todo o galho.
	* @return {HTMLElement[]}
	* @memberOf ICore.dom
	*/
	findChild: function (el, fnc, indepth) {
		var c, r;
		r = [];
		for (var i = 0; i < el.childNodes.length; i++) {
			c = el.childNodes[i];
			if (fnc(c)) {
				r.push(c);
			}
			if (indepth) {
				r = r.concat(this.findChild(c, fnc, indepth));
			}
		}
		return r;
	},
	
	/**
	 * Retorna o X e Y do elemento de acordo com o parent dado. 
	 * 
	 * @param {Object} obj Objeto que ser� avaliado
	 * @param {Object} parent Objeto que ser� o teto da busca
	 * @return {Object}
	 * @memberOf ICore.dom
	 */
	getXYRelative: function (obj, parent) {
		var x = 0, y = 0;
		while (obj && (obj != parent)) {
			y += obj.offsetTop;
			x += obj.offsetLeft;
			obj = obj.offsetParent;
		}
		return {x:x, y:y};
	},
	
	/**
	 * Retorna apenas Y do elemento de acordo com o parent dado.
	 * 
	 * @param {Object} obj Objeto que ser� avaliado
	 * @param {Object} parent Objeto que ser� o teto da busca
	 * @return {Integer}
	 * @memberOf ICore.dom
	 */
	getTop: function (obj, parent) {
		if (!parent) {
			parent = document;
		} 
		var r = 0;
		while (obj && (obj != parent)) {
			r += obj.offsetTop;
			obj = obj.offsetParent;
		}
		return r;
	},
	
	/**
	 * Retorna apenas X do elemento de acordo com o parent dado.
	 * 
	 * @param {Object} obj Objeto que ser� avaliado
	 * @param {Object} parent Objeto que ser� o teto da busca
	 * @return {Integer}
	 * @memberOf ICore.dom
	 */
	getLeft: function (obj, parent) {
		if (!parent) {
			parent = document;
		} 
		var r = 0;
		while (obj) {
			r += obj.offsetLeft;
			obj = obj.offsetParent;
		}
		return r;
	}
};

ICore.util = {

	/**
	 * Se o par�metro o for uma String ele tentar� retornar um HTMLObject com ID igual a obj
	 * sen�o retorna o pr�prio obj.
	 * @param {String} obj
	 * @memberOf ICore.util
	 */
	object: function (obj) {
		if (this.isString(obj)) {
			return ICore.dom.get(obj);
		} else {
			return obj;
		}
	},

	/**
	 * Retorna se o par�metro informado � uma fun��o ou n�o.
	 * @param {Object} f
	 * @memberOf ICore.util
	 */
	isFunction: function (f) {
		return (typeof f == 'function');
	},

	/**
	 * Retorna se o par�metro informado � um Array ou n�o.
	 * @param {Object} a
	 * @memberOf ICore.util
	 */
	isArray: function (a) {
		return (a instanceof Array);
	},

	/**
	 * Retorna se o par�metro informado � uma String ou n�o. 
	 * @param {Object} s
	 * @memberOf ICore.util
	 */
	isString: function (s) {
		return (typeof s == 'string');
	},
	
	/**
	 * Retrona se o par�metro informado � um n�mero ou n�o.
	 * @param {Object} n
	 * @memberOf ICore.util
	 */
	isNumber: function (n) {
		return (typeof n == 'number');
	},

	/**
	 * Retorna se o par�metro informado � indefinido ou n�o.
	 * @param {Object} o
	 * @memberOf ICore.util
	 */
	isUndefined: function (o) {
		return (typeof o == 'undefined');
	}
};

if (!Array.prototype.indexOf) {
	/**
	 * Definindo m�todo n�o implementado no IE.
	 * 
	 * @param {Object} el
	 */
	Array.prototype.indexOf = function (el) {
		for (var i = 0; i < this.length; i++) {
			if (this[i] == el) {
				return i;
			}
		}
		return -1;
	};
}

/**
 * Busca um elemento no vetor e o remove.
 * 
 * @param {Object} el
 * @return {Integer} Retorna o �ndice do elemento que foi removido
 */
Array.prototype.remove = function (el) {
	var i = this.indexOf(el);
	if (i > -1) {
		this.deleteItem(i);
	}
	return i;
};

/**
 * Remove um �nico item do vetor.
 * 
 * @param {Object} index
 */
Array.prototype.deleteItem = function (index) {
	this.splice(index, 1);
};

/**
 * Limpa o vetor.
 */
Array.prototype.clear = function () {
	this.splice(0, this.length);
};

/**
 * Insere um elemento no meio do array.
 */
Array.prototype.insert = function (idx, el) {
	this.splice(idx, 0, el);
};

