/**
 * @author adriano
 */

/* Constantes */
var MAX_INT = 2147483647;
var MIN_INT = -2147483648;

/* Variáveis Globais */

var globalMenus = []; // Variável que controla os menus de uma página
var globalTimers = []; // Variável que controla os timers de uma página
var janelaApoioId = null; // Variável que possui o Id da janela de apoio (para calendário, sugestões, etc...)

/**
 * Copies all the contents of an element to it's parent node and removes it from the document.
 * 
 * @author: adriano
 * @since:  
 * @param {Object} _node
 */
function moveContentsUpAndRemove(_node){
    if(_node.hasChildNodes())
        for(var i=0;i<_node.childNodes.length;i++)
            _node.parentNode.insertBefore(_node.childNodes[i].cloneNode(true),_node);
    _node.parentNode.removeChild(_node);
}

Element.addMethods({
  moveContentsUpAndRemove: function(element) {
    var element = $(element);
    if(element.hasChildNodes())
        for(var i=0;i<element.childNodes.length;i++)
            element.parentNode.insertBefore(element.childNodes[i].cloneNode(true),element);
    var parentNode = element.up(0);
    element.remove();
    return parentNode;
  }
});

/**
 * 
 * @param {Object} _num
 * @param {Object} _caract
 */
String.prototype.lPad = function (_num, _caract) {
	var splitedStr = this.split(''); 
	for (var i = 0; i < _num - this.length; i++) {
		splitedStr.unshift (_caract);
	}; 
	return splitedStr.join('')
}

String.prototype.rPad = function (_num, _caract) {
	var splitedStr = this.split(''); 
	for (var i = 0; i < _num - this.length; i++) {
		splitedStr.push (_caract);
	}; 
	return splitedStr.join('')
}

String.prototype.lTrim = function(chars) {
	chars = chars || "\\s";
	return this.replace(new RegExp("^[" + chars + "]+", "g"), "");
}
 
String.prototype.rTrim = function(chars) {
	chars = chars || "\\s";
	return this.replace(new RegExp("[" + chars + "]+$", "g"), "");
}

String.prototype.trim = function(chars) {
	return this.lTrim(chars).rTrim(chars);
}

Array.prototype.isElementIn = function(_element) {
	var return_value = false;
	for(var i = 0; i < this.length && !return_value; i++)
		if(this[i] == _element) {
			return_value = true;
		}
	return return_value;
}

Array.prototype.insert = function(_value, _loc) {
	_loc = _loc || 0;
	if(_loc == 0)
		this.unshift(_value);
	else {
		var tmpArr = this.slice(0, _loc).concat([_value]).concat(this.slice(_loc, this.length));
		var tmpArrLen = tmpArr.length;
		for (var i = 0; i < tmpArrLen; i++)
			this[i] = tmpArr[i];
	}
}

Array.prototype.append = function(_value) {
	this[this.length] = _value;
}

Array.prototype.remove = function(_value) {
	if(this.indexOf(_value) >= 0)
		this.splice(this.indexOf(_value), 1);
}

Array.prototype.removeAt = function(_index) {
	this.splice(_index);
}

Array.prototype.push = function(_value) {
	this.append(_value);
	return this;
}
/*
Array.prototype.pop = function(_value) {
	var myLength = this.length;
	if(myLength > 0) {
		var value = this[myLength - 1];
		this.remove(myLength - 1);
		return value;
	}
	
}
*/
/**
 * Objecto com determinado identificador (id ou nome). Caso não seja encontrado um objecto com id idêntico a _identificador, é procurado um elemento com nome semelhante.
 * @param {String} _identificador Id ou nome do elemento a seleccionar
 * @return {Object} Objecto(s) com o id ou nome prentendido.
 */
/*function $(_identificador) {
	var __byId = $id(_identificador)
	if(__byId)
		return __byId;
	try {
		var __byName = $name(_identificador, 0);
		return __byName;
	} catch(e) {
		return '';
	}
}*/

/**
 * Objecto com determinado identificador
 * @param {String} _identificador Id do elemento a seleccionar
 * @return {Object} Objecto(s) com o identificador prentendido
 */
function $id(_identificador) {
	return document.getElementById(_identificador);
}

function randomStr(strLen) {
	var alpha = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
	var strLen = strLen || 8;
	var randomstring = '';
	for (var i=0; i < strLen; i++) {
		var randomNum = Math.floor(Math.random() * alpha.length);
		randomstring += alpha.substring(randomNum,randomNum+1);
	}
	return randomstring;
}

/**
 * Objectos com determinado nome
 * @param {String} _tag Nome do elemento a seleccionar
 * @param {Number} _indice Indice do elemento
 * @return {Object} Objecto(s) com o nome prentendido
 */
function $name(_identificador, _indice) {
	return document.getElementsByName(_indentificador)[_indice];
}

/**
 * Objectos com determinada tag
 * @param {String} _tag Tag do elemento a seleccionar
 * @param {Number} _indice Indice do elemento
 * @return {Object} Objecto(s) com o nome prentendido
 */
function $tag(_tag, _indice) {
	if(_indice)
		return document.getElementsByTagName(_tag)[_indice];
	else
		return document.getElementsByTagName(_tag);
}

/**
 * Identificação de um objecto
 * @param {Object} _objecto
 * @return {String} Id do objecto, ou nome, se não possuir id
 */
function r$(_objecto) {
	if(_objecto.id)
		return _objecto.id;
	else if (_objecto.getAttribute('name'))
		return _objecto.getAttribute('name');
}
/**
 * Adiciona um listener a um elemento
 * @param {Object} _elemento Elemento ao qual será associado o evento
 * @param {String} _evento Evento a ser "escutado"
 * @param {Object} _listener Função a ser invocada quanto o evento ocorre.
 * @param {boolean} _bubble 
 */
function adicionaListener(_elemento, _evento, _listener, _bubble) {
	if(_elemento.addEventListener) {
		if(typeof(_bubble) == "undefined")
			_bubble = false;
		_elemento.addEventListener(_evento, _listener, _bubble);
	} else if(this.attachEvent) {
		_elemento.attachEvent("on" + _evento, _listener);
	}
}

/**
 * Elimina o conteúdo de um elemento (todos os filhos do elemento)
 * @param {Object} _elemento Elemento
 */
function limpaConteudo(_elemento) {
	if ( _elemento.hasChildNodes() ) {
		while ( _elemento.childNodes.length >= 1 ) {
		    _elemento.removeChild( _elemento.firstChild );       
		} 
	}
}

/**
 * Verifica se um ficheiro JS já se encontra carregado
 * @param {String} _pathJs
 */
function isJSCarregado(_pathJs) {
	scripts = document.getElementsByTagName('head')[0].getElementsByTagName('script');
	for(var i = 0; i < scripts.length; i++) {
		pathLoc = scripts[i].src.indexOf(_pathJs);
		if(pathLoc > -1 && pathLoc + _pathJs.length == scripts[i].src.length)
			return true;
	}
	return false;
}

/**
 * Carrega um ficheiro Javascript (adiciona-o à zona do Head)
 * @param {String} _pathJs
 */
function carregaJS(_pathJs) {
	if(!isJSCarregado(_pathJs)) {
		var head = document.getElementsByTagName('head')[0];
		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = _pathJs;
		head.appendChild(script);
	}
}

// Com os cumprimentos do Prototype
var $A = function(iterable) {
	if (!iterable) return [];
	if (iterable.toArray) {
		return iterable.toArray();
	} else {
		var results = [];
		for (var i = 0, length = iterable.length; i < length; i++)
			results.push(iterable[i]);
		return results;
	}
}

function getEvento(_ev) {
	var ev = _ev;
	if (!ev) var ev = window.event;
	if (ev.target) targ = ev.target;
	else if (ev.srcElement) targ = ev.srcElement;
	if (targ.nodeType == 3) // bug do Safari
		targ = targ.parentNode;
	return targ;
}

/*
	Gestão de pedidos Ajax.
*/
function AjaxObj(_argumentos) {
	this.inicializado = false;
	this.erroArgs = false;
	this.strArgumentos = "";
	try{
		if(!_argumentos) {
			throw "ParrErr";
		}
		this.argumentos = _argumentos;
	} catch(_erro) {
		if(_erro=="ParrErr") {
			this.erroArgs = true;
		}
		return false;
	}
}

AjaxObj.prototype.iniciar = function() {
	if(this.erroArgs)
		return;
	this.inicializado = true;
	if (typeof XMLHttpRequest != 'undefined') {
		// Estamos a trabalhar com um browser?
		this.xmlHttp = new XMLHttpRequest();
		return;
	}
	else if (window.ActiveXObject) {
		// Não, parece que é só com o IE?
		var actxObj = ["Microsoft.XmlHttp", "MSXML2.XmlHttp", "MSXML2.XmlHttp.3.0", "MSXML2.XmlHttp.4.0", "MSXML2.XmlHttp.5.0"];
		for (var i = actxObj.length -1; i >= 0; i--) {
			try {
				this.xmlHttp = new ActiveXObject(actxObj[i]);
				return;
			} catch(e) {}
		}
	}
	this.inicializado = false;
	throw new Error('XMLHttp não é suportado!');
}

AjaxObj.prototype.carregar = function() {
	if(this.erroArgs)
		return;
	
	if(this.argumentos.sincrono)
		this.sincrono = this.argumentos.sincrono;
	else
		this.sincrono = false;
	if(this.argumentos.argsFuncRetorno) {
		this.argsFuncRetorno = this.argumentos.argsFuncRetorno;
	}
	if(this.argumentos.url)
		this.url = this.argumentos.url;
	if(this.argumentos.metodo)
		this.metodo = this.argumentos.metodo;
	else
		this.metodo = "GET";
	// Simbolo que aparece antes do primeiro argumento é &? true (&) ou false (?)
	if(this.argumentos.firstAmp)
		this.firstAmp = this.argumentos.firstAmp;
	else
		this.firstAmp = true;
	
	if(this.argumentos.parametros)
		this.parametros = this.argumentos.parametros;
	
	if(this.argumentos.callBackSucesso)
		this.callBackSucesso = this.argumentos.callBackSucesso;
	
	if(this.argumentos.idDestino) {
		this.objDestResp = $id(this.argumentos.idDestino);
		this.callBackSucesso = function() {
				var resposta = this.xmlHttp.responseText.replace("\n", "");
				this.objDestResp.innerHTML = resposta;
			}
	}
	else {
		if(this.argumentos.nameDestino) {
			var nameDestino = this.argumentos.nameDestino;
			var indiceDestino = 0;
			if(this.argumentos.indiceDestino)
				this.indiceDestino = this.argumentos.indiceDestino;
			this.objDestResp = $name(nameDestino, indiceDestino);
			this.callBackSucesso = function() {
				var resposta = this.xmlHttp.responseText.replace("\n", "");
				this.objDestResp.innerHTML = resposta;
			}
		}
		else {
			if(this.argumentos.respostaXML) {
				this.callBackSucesso = function() {
					var resposta = this.xmlHttp.responseXML;
					/*if(this.xmlHttp.responseXML.xml)
						// IE way...
						resposta = this.xmlHttp.responseXML.xml;
					else
						// Browsers way!*/
						resposta = this.xmlHttp.responseXML;
					//alert(resposta.childNodes[1].firstChild.xml);
					try {
						var __accoes;
						var	numElementos = resposta.childNodes.length;
						if (resposta.childNodes[1]) {
							// O IE...
							__accoes = resposta.childNodes[1];
							numElementos--;
						}
						else {
							// Os browsers
							__accoes = resposta.firstChild;
						}
						if(numElementos == 1)
							// Conjunto de acções
							if(__accoes.nodeName == 'accoes') {
								if(__accoes.childNodes.length == 0)
									throw new Error("Erro de XML", "Não existem acções definidas.");
								// Vamos lá tratar os elementos
								for(var i = 0; i < __accoes.childNodes.length; i++) {
									var accao = __accoes.childNodes[i];
									switch(accao.nodeName) {
										case 'execjs':
											// Acção "Executar javascript"
											eval(accao.firstChild.nodeValue);
											break;
										case 'updconteudo':
											// Acção "Actualiza conteúdo de um elemento"
											var idElemento, nomeElemento, indiceElemento;
											for(var __atributos = 0; __atributos < accao.attributes.length; __atributos++){
												var __atributo = accao.attributes[__atributos];
												switch(__atributo.nodeName) {
													case 'idelem':
														idElemento = __atributo.nodeValue;
														break;
													case 'nomeelem':
														nomeElemento = __atributo.nodeValue;
														break;
													case 'indiceelem':
														indiceElemento = __atributo.nodeValue;
														break;
													default:
														throw new Error("Erro de XML", "Atributo não esperado.");
														break;
												}
											}
											if(idElemento)
												$(idElemento).innerHTML = accao.firstChild.nodeValue;
											else if(nomeElemento && indiceElemento) {
												$name(nomeElemento, indiceElemento).innerHTML = accao.firstChild.nodeValue;
											}
											else
												throw new Error("Erro de XML", "Erros nos atributos.");
											break;
										default:
											break; 
									}
								}
							}
							// Se vier um XML apenas com um OK, possivelmente virá também uma função nos parametros, para ser executada
							else if(__accoes.nodeName == 'ok') {
								// Testa se essa função está, de facto, definida
								if(this.argumentos.callBackSucesso)
									this.argumentos.callBackSucesso(this.argsFuncRetorno); // Executa-a
							}
							// Se vier um XML apenas com um Erro, então deverá executar a função de excepção, que deverá estar definida
							else if(__accoes.nodeName == 'erro'){
								//<aviso criador="Adriano Teixeira" data="2007-02-17" gravidade="3">Para já, ainda não está nada feito no sentido das funções de excepção, mas é para breve.</aviso>
							}
							else
								throw new Error("Erro de XML", "Elemento não esperado.");
						else
							throw new Error("Erro de XML", "Demasiados elementos.");
					}
					catch(erro) {
						// Para já define para que nada seja feito
					}
				}
			}
		}
	}
}


AjaxObj.prototype.funcaoRetorno = function() {
	if(this.xmlHttp.readyState == 4) {
		if(this.xmlHttp.status == 200) {
			this.callBackSucesso(this.xmlHttp);
			this.xmlHttp = null;
		}
	}
}

AjaxObj.prototype.setFuncaoRetorno = function() {
	var metodo = this.funcaoRetorno, args = $A(arguments), objecto = args.shift();
  	return function() {
    		return metodo.apply(objecto, args.concat($A(arguments)));
  	}
}

AjaxObj.prototype.enviarPedido = function() {
	if (!this.inicializado) {
		this.iniciar();
		this.carregar();
	}
	if(this.parametros) {
		// Se há parâmetros mas nenhum vem definido no proprio url...
		if(this.parametros.length > 0 && !this.firstAmp)
			this.strArgumentos = "?" + encodeURI(this.parametros[0]);
		// Gera a string dos parâmetros à custa dos restantes parâmetros (a partir do segundo), se existirem 
		for(var i = (this.firstAmp?0:1); i < this.parametros.length; i++)
			this.strArgumentos += "&" + encodeURI(this.parametros[i]);
	}
	else {
		this.strArgumentos = "";
	}
/*
	// Define a função de retorno... se o método de envio for assíncrono
	if(this.sincrono)*/
		this.xmlHttp.onreadystatechange = this.setFuncaoRetorno(this);

	// Executa o pedido
	if(this.metodo == "GET") {
		this.xmlHttp.open(this.metodo, this.url + this.strArgumentos, this.sincrono);
		this.xmlHttp.send(null);
	}
	else {
		this.xmlHttp.open(this.metodo, this.url, this.sincrono);
		this.xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		this.xmlHttp.setRequestHeader("Content-length", this.strArgumentos.length);
		this.xmlHttp.setRequestHeader("Connection", "close");
		this.xmlHttp.send(this.strArgumentos);
	}
	

/*
	// Se o método for síncrono, então executa a função após o retorno ocorrer
	if(!this.sincrono)
		this.funcaoRetorno(this.argsFuncRetorno);
*/
}

function Elemento(_id, _elemPai) {
	this.id = _id;
	this.obj = document.getElementById(_id);
	this.elemPai = _elemPai;
}

Elemento.prototype.eleminarElemento = function() {
	this.elemPai.obj.removeChild(this.obj);
}

Elemento.prototype.adicionaFilho = function(_idFilho, _tagElem, _conteudo) {
	var novoElem = document.createElement(_tagElem);
	novoElem.setAttribute("id", _idFilho);
	novoElem.innerHTML = _conteudo;
	this.obj.appendChild(novoElem);
	return (new Elemento(_idFilho, this));
}

/**
--------------------------------
 Motor de Validação Client Side
--------------------------------
**/

/*Um validador deve permitir adicionar campos
sendo possível definir se a validação ocorre num momento para todos ou na ocorrência de um evento para cada um em particular.
Deve ainda ser possível definir as regras de validação a executar. ALém das regras definidas por omissão, deve ainda ser possível
permitir que essas regras sejam traduzidas por uma função, a ser invocada nas mesmas condições acima referidas. */

function Validador() {
	this.metodos = {'change': 'change', 'click': 'click', 'blur': 'blur'};
	this.validacoes = new Array();
}

Validador.prototype.adicionaCampo = function(_campo, _metodoListener, _locMsgErr, _regras) {
	var regras = new Array();
	for(var i = 0; i < _regras.length; i++) {
		var regra = null;
		switch(_regras[i]) {
			case 'email':
				regra = new ValidaEmail(_campo, MSG_ERRO_VALIDA_MAIL, _locMsgErr);
				break;
			case 'obrigatorio':
				regra = new ValidaPreenchido(_campo, MSG_ERRO_VALIDA_NULO, _locMsgErr);
				break;
			default:
				regra = null;
		}
		if(regra)
			regras.push(regra);
	}
	if(_metodoListener in this.metodos) {
		for(var i = 0; i < regras.length; i++) {
			adicionaListener(_campo, _metodoListener, regras[i].setFuncaoValida(regras[i]));
		}
	}
	for(var i = 0; i < regras.length; i++) {
		this.validacoes.push(regras[i]);
	}
}

Validador.prototype.valida = function() {
	var isValido = true;
	for(var i = 0; i < this.validacoes.length; i++) {
		isValido = this.validacoes[i].valida() && isValido;
	}
	return isValido;
}

function ValidaBaseUtil(_campo, _mensagem, _locMsgErr) {
	this.campo = _campo;
	this.mensagem = _mensagem;
	this.locMsgErr = _locMsgErr;
}

ValidaBaseUtil.prototype.getCampoErro = function(_locMsgErro, _nomeCampo) {
	var campos_div = _locMsgErro.getElementsByTagName("div");
	var campo_erro = null;
	for(var i = 0; i < campos_div.length; i++)
		if(campos_div[i].id == _nomeCampo) {
			return campos_div[i];
		}
}

function ValidaEmail(_campo, _mensagem, _locMsgErr) {
	this.campo = _campo;
	this.mensagem = _mensagem;
	this.locMsgErr = _locMsgErr;
}

ValidaEmail.prototype.setFuncaoValida = function() {
	var metodo = this.valida, args = $A(arguments), objecto = args.shift();
  	return function() {
    		return metodo.apply(objecto, args.concat($A(arguments)));
  	}
}

ValidaEmail.prototype.valida = function() {
	var filter_reg_exp=/^.+@.+\..{2,3}$/;
	var campo_erro = (new ValidaBaseUtil()).getCampoErro(this.locMsgErr, "asi_err_mail_" + r$(this.campo));
	if(!filter_reg_exp.test(this.campo.value)) {
		if(!campo_erro) {
			var novoElem = document.createElement('div');
			novoElem.setAttribute('id',"asi_err_mail_" + r$(this.campo));
			novoElem.innerHTML = this.mensagem;
			this.locMsgErr.appendChild(novoElem);
		}
		return false;
	}
	else {		
		if(campo_erro)
			this.locMsgErr.removeChild(campo_erro);
	}
	return true;
}

function ValidaPreenchido(_campo, _mensagem, _locMsgErr) {
	this.campo = _campo;
	this.mensagem = _mensagem;
	this.locMsgErr = _locMsgErr;
}

ValidaPreenchido.prototype.setFuncaoValida = function() {
	var metodo = this.valida, args = $A(arguments), objecto = args.shift();
  	return function() {
    		return metodo.apply(objecto, args.concat($A(arguments)));
  	}
}

ValidaPreenchido.prototype.valida = function() {
	var campo_erro = (new ValidaBaseUtil()).getCampoErro(this.locMsgErr, "asi_err_null_" + r$(this.campo));
	if(this.campo.value.length == 0) {
		if(!campo_erro) {
			var novoElem = document.createElement('div');
			novoElem.setAttribute('id',"asi_err_null_" + r$(this.campo));
			novoElem.innerHTML = this.mensagem;
			this.locMsgErr.appendChild(novoElem);
		}
		return false;
	}
	else {
		if(campo_erro)
			this.locMsgErr.removeChild(campo_erro);
	}
	return true;
}
/**
 * Objecto menu simples
 * @param {String} _botaoMenuId
 * @param {String} _blocoMenuId
 * @param {MenuSimples} _menuPai
 */
function MenuSimples(_botaoMenuId, _blocoMenuId, _menuPai) {
	this.botaoMenu = $(_botaoMenuId);
	this.blocoMenu = $(_blocoMenuId);
	this.classeEscondido = elementoEscondidoCSS;
	this.aberto = false;
	this.menuPai = _menuPai;
	this.filhos = []
}

/**
 * Abertura do menu
 */
MenuSimples.prototype.abre = function() {
	if(this.aberto)
		clearTimeout(globalTimers[this.botaoMenu.id])
	/*
	var posEscondido = this.blocoMenu.className.indexOf(this.classeEscondido);
	var tamanhoClasseEscondido = this.classeEscondido.length;
	this.blocoMenu.className = (posEscondido>=0?this.blocoMenu.className.substr(0, posEscondido) + (posEscondido+tamanhoClasseEscondido<this.blocoMenu.className.length?this.blocoMenu.className.substring(posEscondido+tamanhoClasseEscondido+1, this.blocoMenu.className.length - 1): ''): this.blocoMenu.className);
	*/
	delClasse(this.blocoMenu, this.classeEscondido);
	this.aberto = true;
}

/**
 * Fecho do menu
 */
MenuSimples.prototype.fecha = function() {
	/*
	var posEscondido = this.blocoMenu.className.indexOf(this.classeEscondido);
	this.blocoMenu.className = (posEscondido==-1?this.blocoMenu.className + ' ' + this.classeEscondido: this.blocoMenu.className);
	*/
	addClasse(this.blocoMenu, this.classeEscondido);
	this.aberto = false;
}

/**
 * Executa a abertura do menu (se este estiver fechado) ou vice-versa.
 */
MenuSimples.prototype.abre_fecha = function() {
	if(this.aberto)
		this.fecha()
	else
		this.abre()
}

/**
 * Adiciona um componente filho ao menu actual
 * @param {Object} _botaoMenuId
 * @param {Object} _blocoMenuId
 */
MenuSimples.prototype.adicionaFilho = function(_botaoMenuId, _blocoMenuId) {
	this.filhos[_botaoMenuId] = this.primeiraAbertura(_botaoMenuId, _blocoMenuId);
}

/**
 * Tratamento do evento que controla a primeira abertura de um menu simples
 * @param {String} _botaoMenuId
 * @param {String} _blocoMenuId
 * @return {MenuSimples}
 */
MenuSimples.prototype.primeiraAbertura = function(_botaoMenuId, _blocoMenuId) {
	globalMenus[_botaoMenuId] = new MenuSimples(_botaoMenuId, _blocoMenuId);
	
	//globalMenus[_botaoMenuId].botaoMenu.onclick = function () {globalMenus[_botaoMenuId].abre_fecha(); return false;};
	globalMenus[_botaoMenuId].botaoMenu.onmouseover = function () {globalMenus[_botaoMenuId].abre();};
	globalMenus[_botaoMenuId].botaoMenu.onmouseout = function () {globalTimers[_botaoMenuId] = setTimeout("globalMenus['"+_botaoMenuId+"'].fecha()", 200);};
	globalMenus[_botaoMenuId].blocoMenu.onmouseover = function () {globalMenus[_botaoMenuId].abre();};
	globalMenus[_botaoMenuId].blocoMenu.onmouseout = function () {globalTimers[_botaoMenuId] = setTimeout("globalMenus['"+_botaoMenuId+"'].fecha()", 200);};
	globalMenus[_botaoMenuId].abre();
	return globalMenus[_botaoMenuId];
}

/**
 * Objecto responsável pelos parametros necessários aos OPA (Objectos de Preenchimento Automatizado)
 */
var OPA = Class.create({

	initialize: function() {
		this.componentes = {};
		this.valores = {};
	},
	adicionaElemento: function(elemento, indiceValor) {
		this.janela.show();
	},
	preencheValores: function() {
		this.janela.hide();
	},	
	addComponente: function(indice, componente) {
		this.componentes[indice] = componente;
	},
	addValor: function(indice, valor) {
		this.valores[indice] = valor;
	},
	setValores: function(valores) {
		this.valores = valores;
	},
	preencheComponentes: function() {
		if(this.componentes)
			for(var indice in this.valores) {
				if(this.componentes[indice])
					switch(this.componentes[indice].tagName) {
						case 'INPUT':
							this.componentes[indice].value = this.valores[indice];
							break;
						case 'DIV':
						case 'SPAN':
							this.componentes[indice].innerHTML = this.valores[indice];
							break;
						default:
							null;
					}
			}
	}
});

var Paginator = Class.create();

Object.extend(Paginator.prototype, {
    VIS_FIELD_FOCUS: 0,
    VIS_CONSTANT: 1,
		
    options: {
        title: null,
        width: '400px',
        height: '200px',
        parameters: {},
        visibility: 0 // 0 is equivalent to VIS_FIELD_FOCUS
    },
    
    /**
     * 
     * @param field: 
     * @param url:
     * @param options: 
     */
    initialize: function(paginatorID, formID, baseURL, options){
    	this.paginatorObj = $(paginatorID);
        this.formObj = $(formID);
        this.baseURL = baseURL;
        Object.extend(this.options, options ||
        {});
        var input_text_selectors = this.paginatorObj.select('input.paginator_box_sel');
        var input_text_selector = null;
        if(input_text_selectors.length == 1)
        	this.input_text_selector = input_text_selectors[0];
        else {
        	// TODO: Create an hidden input to deploy the destiny page
        }
        var direct_selectors = this.paginatorObj.select('a.paginator_direct_sel');
        for (var i = 0; i < direct_selectors.length; i++) {
        	direct_selectors[i].observe('click',this.direct_page_click.bindAsEventListener(this), false);
        }
    },
    
    direct_page_click: function(event) {
    	var element = Event.element(event);
    	try {
    	//alert(element.innerHTML);
    	this.input_text_selector.value = element.innerHTML;
    	this.formObj.fire('asi:submit');
    	}
    	catch(e) {
    		alert(e.toString());
    	}
	    Event.stop(event);
    }
});

function autoCompleteCallBackFactory(idElemAfterUpdate) {
	return function(textElem, queryString) { $(idElemAfterUpdate).writeAttribute("value", ""); return queryString; };
}

function autoCompleteAfterUpdateFactory(idElemAfterUpdate) {
	return function(textElem, liElem) { $(idElemAfterUpdate).writeAttribute("value", liElem.readAttribute("id")); };
}

function emptyFunction() {}

function executeOnLoad(funct, onLoad) {
	if (onLoad)
		document.observe("dom:loaded", funct, false);
	else {
		funct();
	}
}

function executeFunction() {
	var args = $A(arguments).slice(0);
	var event = args.shift();
	var functAndArgs = args.shift().slice(0);
	var functionName = functAndArgs.shift();
	return functionName.apply(this, [event].concat(functAndArgs));
}

function registerEvent() {
	var args = $A(arguments);
	var element = args.shift();
	var event = args.shift();
	//var executeFunction = args.shift();
	//alert("executeFunction = " + executeFunction);
	//alert("args = " + args);
	$(element).observe(event, executeFunction.bindAsEventListener(this, args));
}

function registerBindedEvent() {
	var args = $A(arguments);
	var element = args.shift();
	var event = args.shift();
	var thisObj = args.shift();
	//var executeFunction = args.shift();
	//alert("executeFunction = " + executeFunction);
	//alert("args = " + args);
	$(element).observe(event, executeFunction.bindAsEventListener(thisObj, args));
	
}

/*function registerEventClass() {
	var args = $A(arguments);
	var element = args.shift();
	var event = args.shift();
	$(element).observe(event, executeClass).bindAsEventListener.apply(this, args);
}*/


function wrap (f) {
	return function () {
		f.apply(this, arguments);
		alert(f);
		this.prototype = f.prototype;
		return this;
	};
}

function executeClass() {
	var args = Array.prototype.slice.call(arguments); 
	alert(args);
	  var event = args.shift(); 
	  var func = args.shift(); 
	  alert(func[0]);
	  
	  x= func[0].bind(this, args);
	  /*return function() { 
	    return func[0].apply(func[0], [event].concat(Array.prototype.slice.call(func[1]))); 
	  }; */
/*	
	var args = $A(arguments);
	args.shift();
	var functAndArgs = args.shift();
	alert(functAndArgs[0]);
	return new function() {
		functAndArgs[0].apply(this, functAndArgs[1]);
	}
	*///new functAndArgs[0](functAndArgs[1]);
	//return new t();
}

function getElementsBySelectors(selectorsList) {
	return $$(selectorsList.join(' '));
}

