/**
 * Faz validação de campos de formulário
 * @author Michael Henrique Siegwarth
 */

function FormUtils(classeSpanErro, classeInputErro, classeInputLimpo) {
	this.classeSpanErro = classeSpanErro;
	this.classeInputErro = classeInputErro;
	this.classeInputLimpo = classeInputLimpo;
	this.erro = false;
	
	/**
	 * Retorna a variável erro
	 */
	this.getErro = function() {
		return this.erro;
	}
	
	/**
	 * Reseta a variável de erro. Ela é setada quando alguma função de verificação falha
	 */
	this.resetErro = function() {
		this.erro = false;
	}
	
	/**
	 * Seta um span com o estilo de erro e mensagem de erro
	 * @param {Object} idSpan Id do span a ser preenchido
	 * @param {Object} mensagem Mensagem de erro a ser colocada no span
	 */
	this.setarSpanErro = function(idSpan, mensagem) {
		document.getElementById(idSpan).innerHTML = mensagem;
		document.getElementById(idSpan).className = this.classeSpanErro;
	}
	
	/**
	 * Limpa um span
	 * @param {Object} idSpan Id do span a ser limpo
	 */
	this.setarSpanLimpo = function(idSpan) {
		document.getElementById(idSpan).innerHTML = "";
	}
	
	this.setarInputLimpo = function(idCampo) {
		document.getElementById(idCampo).className = this.classeInputLimpo;
	}
	
	this.setarInputErro = function(idCampo) {
		document.getElementById(idCampo).className = this.classeInputErro;
	}
	
	/**
	 * Verifica se um campo está vazio
	 * @param {Object} idCampo Id do campo a ser verificado
	 * @param {Object} idSpan Id do span a ser eventualmente preenchido com um erro
	 * @param {Object} mensagem Mensagem de erro a ser colocada no span
	 */
	this.isVazio = function(idCampo, idSpan, mensagem) {
		if(document.getElementById(idCampo).value != "") {
			this.setarSpanLimpo(idSpan);
			this.setarInputLimpo(idCampo);			
			return false;
		}
		else {
			this.setarSpanErro(idSpan, mensagem);
			this.setarInputErro(idCampo);
			this.erro = true;
			return true;
		}
	}
	
	/**
	 * Verifica se um campo é um número válido
	 * @param {Object} idCampo Id do campo a ser verificado
	 * @param {Object} idSpan Id do span a ser eventualmente preenchido com um erro
	 * @param {Object} mensagem Mensagem de erro a ser colocada no span
	 */
	this.isNumero = function(idCampo, idSpan, mensagem) {
		str = document.getElementById(idCampo).value;
		
		var reg = /^(-)?(\d*)(\.?)(\d*)$/;
		
		if (!str.match(reg)) {
			this.setarSpanErro(idSpan, mensagem);
			this.setarInputErro(idCampo);
			
			this.erro = true;
			
			return false;
		}
		
		this.setarSpanLimpo(idSpan);
		this.setarInputLimpo(idCampo);
		document.getElementById(idCampo).className = this.classeInputLimpo;
		return true;
	}
	
	/**
	 * Verifica se um campo é válido segundo uma expressão regular
	 * @param {Object} idCampo Id do campo a ser verificado
	 * @param {Object} idSpan Id do span a ser eventualmente preenchido com um erro
	 * @param {Object} mensagem Mensagem de erro a ser colocada no span
	 * @param {string} argument Expressão regular. (O quarto argumento)
	 */
	this.isCharValido = function(idCampo, idSpan, mensagem) {
		str = document.getElementById(idCampo).value;
		
		var reg = "/";
		reg+=arguments[3];
		reg+="/gi";
		//reg=/[0-9]{4}[\/][0-9]{4}$/;
		//reg=/(\d*)[\.|\/|-](\d*)$/;
		if (!str.match(eval(reg))) {
			this.setarSpanErro(idSpan, mensagem);
			this.setarInputErro(idCampo);
			this.erro = true;
			return false;
		}
		this.setarSpanLimpo(idSpan);
		this.setarInputLimpo(idCampo);
		document.getElementById(idCampo).className = this.classeInputLimpo;
		return true;
	}
	
	/**
	 * Verifica se o comprimento de um campo está dentro de um limite estabelecido
	 * @param {Object} idCampo Id do campo a ser verificado
	 * @param {Object} comprimentoMinimo Comprimento mínimo do campo
	 * @param {Object} comprimentoMaximo Comprimento máximo do campo
	 * @param {Object} idSpan Id do span a ser eventualmente preenchido com um erro
	 * @param {Object} mensagem Mensagem de erro a ser colocada no span
	 */
	this.verificarComprimento = function(idCampo, comprimentoMinimo, comprimentoMaximo, idSpan, mensagem) {
		str = document.getElementById(idCampo).value;
		if(str.length >= comprimentoMinimo && str.length <= comprimentoMaximo) {
			this.setarSpanLimpo(idSpan);
			this.setarInputLimpo(idCampo);
			document.getElementById(idCampo).className = this.classeInputLimpo;
			return true;
		}
		
		this.setarSpanErro(idSpan, mensagem);
		this.setarInputErro(idCampo);
		this.erro = true;
		return false;
	}

	/**
	 * Verifica se um campo é um e-mail
	 * @param {Object} idEmail Id do campo de e-mail a ser verificado
	 * @param {Object} idSpan Id do span a ser eventualmente preenchido com um erro
	 * @param {Object} mensagem Mensagem de erro a ser colocada no span
	 */
	this.isEmail = function(idEmail, idSpan, mensagem) {
		var email = document.getElementById(idEmail).value;
	
		if (window.RegExp) {
			var reg1str = "(@.*@)|(\\.\\.)|(@\\.)|(\\.@)|(^\\.)";
			var reg2str = "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$";
			var reg1 = new RegExp(reg1str);
			var reg2 = new RegExp(reg2str);
	
			if (!reg1.test(email) && reg2.test(email)) {
				this.setarSpanLimpo(idSpan);
				this.setarInputLimpo(idEmail);
				document.getElementById(idEmail).className = this.classeInputLimpo;
				return true;
			}
			
			this.setarSpanErro(idSpan, mensagem);
			this.setarInputErro(idEmail);
			
			this.erro = true;
			
			return false;
		}
		else {
			if(email.indexOf("@") >= 0) {
				this.setarSpanLimpo(idSpan);
				this.setarInputLimpo(idEmail);
				return true;
			}
	
			this.setarSpanErro(idSpan, mensagem);
			this.setarInputErro(idEmail);
			
			this.erro = true;
			
			return false;
		}
	}
	
	/**
	 * Verifica se dois campos tem o mesmo conteúdo
	 * @param {Object} idCampo1 Primeiro campo a ser comparado
	 * @param {Object} idCampo2 Segundo campo a ser comparado
	 * @param {Object} idSpan Id do span a ser eventualmente preenchido com um erro
	 * @param {Object} mensagem Mensagem de erro a ser colocada no span
	 */
	this.compararCampos = function(idCampo1, idCampo2, idSpan, mensagem) {
		if(document.getElementById(idCampo1).value == document.getElementById(idCampo2).value) {
			this.setarSpanLimpo(idSpan);
			this.setarInputLimpo(idCampo);
			return true;
		}
		
		this.setarSpanErro(idSpan, mensagem);
		this.setarInputErro(idCampo);
		
		this.erro = true;
		
		return false;
	}
}


/**
 * Classe Formulario. 
 * Possui funcionalidades para manipular formulários.
 * @author Rodolfo Emílio Rickli Neto
 * @classDescription Classe Formulario. Possui funcionalidades para manipular formulários.
 * @param {Object} idForm ID do formulário que será criado.
 */
function Formulario(idForm){
	/**
	 * @type element Referência ao elemento de formulário <form>.
	 */
	this.pai;
	/**
	 * @type element Referência ao elemento que será adicionado ao formulário.
	 */
	this.filho;
	/**
	 * @type String Texto utilizado para descrever um campo do formulário.
	 */
	this.campoLabel;
	/**
	 * Criação do elemento pai <form>.
	 * Se o elemento <form> já existir, cria referência ao já existente.
	 * @constructor
	 * @param {Object} idForm ID do novo formulário.
	 */
	this.Formulario = function(idForm){
		this.pai = document.getElementById(idForm);
		if(!this.pai){
			this.pai = document.createElement("form");
			this.pai.id = idForm;
		}
	}
	/**
	 * Chamada do construtor.
	 * @see this.Formulario
	 */
	this.Formulario(idForm);
	/**
	 * Adiciona o formulário no documento HTML. 
	 * Se não for definido o id do elemento pai, coloca no corpo do documento.
	 * Se o nome do elemento pai for inválido, não adiciona o formulário. 
	 * @param {Object} idPai ID do elemento pai que recebe o formulário.
	 */
	this.exibir = function(idPai){
		if(!idPai)
			document.lastChild.lastChild.appendChild(this.pai);
		else if( document.getElementById(idPai) )
			document.getElementById(idPai).appendChild(this.pai);
	}
	
	/**
	 * Adiciona um tag filho qualquer ao formulário
	 */
	this.append = function(novoFilho) {
		this.pai.appendChild(novoFilho);
	}
	
	/**
	 * Adiciona um elemento <input> ao formulário.
	 * Coloca abaixo do último elemento na lista de elementos filho do formulário.
	 * O último parâmetro permite adicionar um texto descritivo junto (antes) do elemento <input>.
	 * @param {Object} tipo Tipo do elemento (text,password,hidden,checkbox,radio,...)
	 * @param {Object} id ID do novo elemento <input> (atributo 'id').
	 * @param {Object} vlr Valor do elemento (atributo 'value').
	 * @param {Object} txt Texto descritivo que será colocado antes do elemento <input>.
	 * @param  {Object} posicaoTxt Se o texto será colocado antes ou depois do elemento <input>.
	 */
	this.campoInput = function(tipo,idCampo,vlr,txt,posicaoTxt){
		//alert(posicaoTxt);
		this.filho = document.createElement("input");
		this.filho.type = tipo;
		this.filho.id = idCampo;
		if(vlr)
			this.filho.value = vlr;
		this.pai.appendChild(this.filho);
		if(txt){
			this.campoLabel = txt;
			this.insLabel(posicaoTxt);
		}
	}
	
	/**
	 * Cria um elemento HTML select
	 * @param (Array) optionArray Array no qual cada elemento é o conteúdo de um option
	 * @param {Object} txt Texto descritivo que será colocado antes do elemento <input>.
	 * @param  {Object} posicaoTxt Se o texto será colocado antes ou depois do elemento <input>.
	 */
	this.campoSelect = function(optionArray,idCampo, txt,posicaoTxt) {
		this.filho = document.createElement("select");
		
		for(var i=0; i<optionArray.length; i++) {
			var novaOption = document.createElement("option");
			novaOption.innerHTML = optionArray[i];
			
			this.filho.appendChild(novaOption);	
			
		}
		
		this.filho.id = idCampo;
		
		this.pai.appendChild(this.filho);
		
		// Se não tiver texto, nem crie o label
		if(txt){
			this.campoLabel = txt;
			this.insLabel(posicaoTxt);
		}
	}
	
	/**
	 * Insere uma quebra de linha no formulário. Tag <br>.
	 */
	this.br = function(){
		this.filho = document.createElement("br");
		this.pai.appendChild(this.filho);
		this.filho.style.clear = "left";
	}
	
	/**
	 * Insere uma linha no formulário. Tag <hr>.
	 */
	this.hr = function(){
		this.filho = document.createElement("hr");
		this.pai.appendChild(this.filho);
		this.filho.style.clear = "left";
	}
	
	/**
	 * Método que desabilita todos os campos do formulário
	 */
	this.disableForm = function(){
		//alert(this.pai.childNodes);
	}
	/**
	 * Insere um elemento <div> no formulário.
	 * @param {Object} idDiv ID do elemento (atributo 'id').
	 */
	this.div = function(idDiv){
		this.filho = document.createElement("div");
		this.filho.id = idDiv;
		this.pai.appendChild(this.filho);
	}
	/**
	 * Insere o elemento <label> associado ao último elemento de formulário que foi inserido.
	 * Utiliza o atributo this.campoLabel.
	 */
	this.insLabel = function(posicao){
		//alert(posicao);
		var campoLabel;
		campoLabel = document.createElement("label");
		campoLabel.id = this.filho.id+"Label";
		campoLabel.innerHTML = this.campoLabel;
		campoLabel.setAttribute("for",this.filho.id);
		if(posicao && posicao == "depois")
			this.pai.appendChild(campoLabel);
		else
			this.pai.insertBefore(campoLabel,this.filho);
	}
	/**
	 * Função que atribui um texto para exibir antes dos elementos do formulário.
	 * @param {Object} txt Texto de exibição. 
	 */
	this.setLabel = function(txt){
		this.campoLabel = txt;
	}
	/**
	 * Faz referência a um elemento de formulário (geralmente o elemento <form>).
	 * @param {Object} pai ID do elemento HTML.
	 */
	this.setPai = function(idPai){
		this.pai = document.getElementById(idPai);
	}
	
	this.span = function(idSpan, texto) {
		this.filho = document.createElement("span");
		this.filho.id = idSpan;
		this.filho.innerHTML = texto;
		this.pai.appendChild(this.filho);
	}
	
	this.texto = function(idSpan, texto) {
		this.filho = document.createElement("span");
		this.filho.id = idSpan;
		this.filho.innerHTML = texto;
		this.pai.appendChild(this.filho);
	} 

}
/**
 * Função que limpa os dados de um formulário (reset).
 * @param {Object} nomeForm Nome do formulário a ser limpado.
 */
function limparFormulario(nomeForm){
	document.getElementById(nomeForm).reset();
}
/**
 * Limpa o valor de um elemento (reset).
 * @param {Object} idEl ID do elemento.
 */
function limparCampo(idEl){
	document.getElementById(idEl).reset();//.value="";
}
/**
 * Função que remove um elemento HTML.
 * @todo Testar a função para outros tipos de elementos além do <form>.
 * @param {Object} nomeForm Nome do elemento que será removido. 
 */
function remElemento(nomeElemento){
	var pai;
	var filho = document.getElementById(nomeElemento);
	if(filho){
		pai = filho.parentNode;
		pai.removeChild(filho);
	}
}
/**
 * Função que coloca uma mensagem em um elemento HTML (innerHTML).
 * @param {Object} msgBox O elemento onde a mensagem será colocada (innerHTML).
 * @param {Object} n Tempo em segundos.
 * @param {Object} t Variável que aponta para o timer.
 * @param {Object} msg A mensagem.
 */
function setMensagem(msgBox, msg, n, t,tipoMsg){
	var img = "";
	var classeCSS = "";
	switch(tipoMsg){
		case "warn":
			img = "<img src=\"img/16-message-warn.png\" /> ";
			classeCSS = "msgErro";
			break;
		case "info":
			img = "<img src=\"img/16-message-info.png\" /> ";
			classeCSS = "msgSucesso";
	}
	/**
	 * Limpa o timer se ele existir.
	 */
	if(t) clearTimeout(t);
	/**
	 * Se mensagem for em branco, coloca um espaço em branco.
	 */
	if(msg == "" || msg == "&nbsp;") 
		msg = "&nbsp;";
	else
		msg = img+msg+"</img>";
	/**
	 * Coloca a nova mensagem na <div> de mensagens.
	 */
	document.getElementById(msgBox).innerHTML=msg;
	if(classeCSS != "")
		document.getElementById(msgBox).className = classeCSS;
	/**
	 * Apaga a mensagem após n segundos. Se for -1 nunca apaga a msg.
	 */
	if( n >= 0)
		t = setTimeout(function(){document.getElementById(msgBox).innerHTML='&nbsp;'},n*1000);
}
/**
 * Função que limpa uma mensagem após n segundos.
 * Se n = 0, apaga imediatamente.
 * @todo Rever a utilidade desta função. Utilizar função setMensagem.
 * @param {Object} msgBox O elemento onde a mensagem será colocada (innerHTML).
 * @param {Object} n Tempo em segundos.
 * @param {Object} t Variável que aponta para o timer.
 */
function remMensagem(msgBox, n, t){
	t = setTimeout(function(){document.getElementById(msgBox).innerHTML='&nbsp;'},n*1000);
}
/**
 * Método que insere um método relacionado à um evento em um elemento.
 * @param {Object} elemento Identificador do elemento que receberá o evento.
 * @param {Object} evento Tipo de evento (click, mouseover,submit,keyup,etc.).
 * @param {Object} metodo O método que será chamado no evento.
 */
function insEvento(elemento,evento,metodo){
	
	var tmp = document.getElementById(elemento);
	if(tmp) {
			
		if(tmp.addEventListener){ // Mozilla
			tmp.removeEventListener(evento,metodo,false);
			tmp.addEventListener(evento,metodo,false);
		}
		else{ // IE
			tmp.detachEvent("on"+evento,metodo);
			tmp.attachEvent("on"+evento,metodo);
		}	
	}
}
/**
 * Método que remove um método relacionado ao evento em um elemento.
 * @param {Object} elemento Elemento que será removido o evento associado.
 * @param {Object} evento Tipo de evento que será removido (click, mouseover,submit,keyup,etc.).
 * @param {Object} metodo O método que será removido do evento.
 */
function remEvento(elemento,evento,metodo){
	var tmp = document.getElementById(elemento);
	if(tmp) {
		if(tmp.removeEventListener){ // Mozilla
			tmp.removeEventListener(evento,metodo,false);
		}
		else{ // IE
			tmp.detachEvent("on"+evento,metodo);
		}
	}
}
/**
 * Retorna o conteúdo de um elemento de uma tag XML.
 * 
 * 		A partir de um documento XML (xmlDoc), é criado um vetor contendo vários elementos de mesmo nome de tag (idEl).
 * 		A partir deste vetor, a função retorna o valor da tag no índice desejado (i).
 * @todo Rever a utilidade desta função (comparado à função getElementoForm).
 * @param {Object} xmlDoc O documento XML onde está a tag procurada.
 * @param {Object} idEl O nome da tag procurada.
 * @param {Object} i O índice do vetor de tags de mesmo nome.
 */
function getElementoXML(xmlDoc,idEl,i){
	var tmp = xmlDoc.getElementsByTagName(idEl);

	if( tmp[i] && tmp[i].firstChild )
		tmp = tmp[i].firstChild.nodeValue;
	else
		tmp = "";
		
	return tmp;
}

function insEventoForm(idForm, evento, metodo, inputType) {
	
	var formulario = document.getElementById(idForm);
	
	if( inputType == "" || inputType == null ) {
		inputType = "text";
	}
				
	for(var i=0; i<formulario.length; i++ ) {
		
		if( formulario[i].type == inputType ) {
			insEvento(formulario[i].id,evento,metodo);
		}
		
	}
	
}
/**
 * Esta função tem o mesmo papel da função setAtributo, mas aplica a todos os elementos de um formulário.
 * @param {Object} idForm Identificador do formulário.
 * @param {Object} atr Atributo a ser inserido nos elementos do formulário.
 * @param {Object} vlrAtr O valor do atributo.
 * @param {Object} inputType Tipo de campo input que receberá o atributo (text, radio, select, etc...).
 */
function setAtributoForm(idForm, atr, vlrAtr, inputType) {
	
	var formulario = document.getElementById(idForm);

	if( inputType == "" || inputType == null ) {
		inputType = "text";
	}
				
	for(var i=0; i<formulario.length; i++ ) {
		
		if( formulario[i].type == inputType ) {
			setAtributo(formulario[i].id,atr,vlrAtr);
		}
		
	}
	
}
	
/**
 * Esta função retorna o valor de um elemento HTML.
 * @param {Object} idEl ID do elemento HTML.
 */
function getValorElemento(idEl){
	var tmp = document.getElementById(idEl);
	
	if( tmp ) {
		if(tmp.type == "checkbox") {
			if(tmp.checked) {
				return 1;
			}
			else {
				return 0;
			}
		}
		// Se for select
		else if(tmp.type == "select" || tmp.type == "select-one") {
			return tmp.options[tmp.selectedIndex].value;
		}
		else {
			return tmp.value;
		}		
	}
	else {
		return "";
	}
}
/**
 * Função que atribui um valor ao elemento HTML. 
 * @param {Object} idEl ID do elemento HTML.
 * @param {Object} valor O valor que será atribuído ao elemento.
 */
function setValorElemento(idEl,valor){
	var tmp = document.getElementById(idEl);
	
	if( tmp ) {
		// Se for checkbox
		if(tmp.type == "checkbox") {
			
			if(valor == '1') {
				tmp.checked = true;
			}
			else {
				tmp.checked = false;
			}
		}
		// Se for select
		else if(tmp.type == "select" || tmp.type == "select-one") {
			for(var i=0; i< tmp.options.length; i++) {
				if(tmp.options[i].value == valor) {
					tmp.selectedIndex = i;
					break;
				}
			}
		}
		// Se for outra coisa
		else {
			tmp.value = valor;	
		}
		
	}
}
/**
 * Função que habilita um elemento HTML e atribui uma classe CSS.
 * @param {Object} idCampo ID do elemento HTML.
 * @param {Object} classeCSS Nome da classe CSS que será aplicada.
 */
function campoAtivo(idCampo,classeCSS){
	var tmp;
	
	tmp = document.getElementById(idCampo);
	//tmp.value = valor;
	tmp.disabled = false;
	tmp.className = classeCSS;//"campoAtivo";
}
/**
 * Função que desabilita um elemento HTML e atribui uma classe CSS.
 * @param {Object} idCampo ID do elemento HTML.
 * @param {Object} classeCSS Nome da classe CSS que será aplicada.
 */
function campoInativo(idCampo,classeCSS){
	var tmp;
	
	tmp = document.getElementById(idCampo);
	//tmp.value = valor;
	tmp.disabled = true;
	tmp.className = classeCSS;//"campoInativo";
}
/**
 * Verifica se um elemento existe na página.
 * @param {Object} elemento ID do elemento HTML.
 */
function existeElemento(elemento){
	if( document.getElementById(elemento) )
		return true;
	else
		return false;
}
/**
 * Insere um atributo ao elemento HTML.
 * @param {Object} idCampo ID do elemento que recebe o atributo.
 * @param {Object} atr Atributo a ser inserido ao elemento.
 * @param {Object} vlrAtr Valor do atributo.
 */
function setAtributo(idCampo,atr,vlrAtr){
	var tmp = document.getElementById(idCampo);

	if(tmp != null) {	
		/**
		 * Este switch é necessário para os atributos:
		 * 	- disabled
		 *  - checked
		 *  - visibility (atributo de 'style')
		 * Por algum motivo estes atributos não funcionam através da opção 'default'.
		 */
		switch(atr){
			case "disabled":
				tmp.disabled = vlrAtr;
				break;
			case "checked":
				tmp.checked = vlrAtr;
				break;
			case "visibility":
				tmp.style.visibility = vlrAtr;
				break;
			case "className":
				tmp.className = vlrAtr;
				break;
			default:
				tmp.removeAttribute(atr);
				tmp.setAttribute(atr,vlrAtr);
		}
	}
}
/**
 * Função que retorna o valor de um atributo do elemento HTML.
 * @todo Verificar porque alguns atributos não são retornados (ex.: atr checked).
 * @param {Object} idCampo ID do elemento HTML.
 * @param {Object} atr O nome do atributo.
 */
function getAtributo(idCampo,atr){
	var tmp = document.getElementById(idCampo);
	switch(atr){
		case "checked":
			return tmp.checked;
			break;
		default:
			return tmp.getAttribute(atr);
	}
}
