/**
@name LibValorTitulo.js
@description Implementa métodos para validação do campo observação de um título
@methods
@created 12/05/2004
@author Jorge Bittencourt
*/


//*************************************************************************************************************
/**
@name LibValorTitulo
@description Construtor dessa classe
@created 22/03/2004
@param numeroLinhas: o múmero máximo de linhas
@param numeroColunas: o número máximo de colunas
@param abatimentoName: o nome do campo de abatimento
@param prazoProtestoName: o nome do campo que determina o prazo de protesto do título
@param iofName: o nome do campo do iof
@param jurosName: o nome do campo do juros
@param multaName: o nome do campo da multa
@param valorDesconto1Name: o nome do campo do primeiro valor de desconto
@param valorDesconto2Name: o nome do campo do segundo valor de desconto
@param valorDesconto3Name: o nome do campo do terceiro valor de desconto
@param observacaoName: o nome do campo de observação
@param observacaoText: o nome do campo onde o número de linhas disponíveis é exibido
@param msgErro: a mensagem de erro a ser exibida se houver um erro na validação
@return Não retorna nada
@author Jorge Bittencourt
*/
function LibObservacaoTitulo(numeroLinhas, numeroColunas, abatimentoName, prazoProtestoName, 
	iofName, jurosName, multaName, valorDesconto1Name, valorDesconto2Name, valorDesconto3Name, 
	observacaoName, observacaoText, msgErro)

{
	// recupere os inputs e armazene referências a eles
	eval('this.inputAbatimento = document.all.item("' + abatimentoName + '");');
	eval('this.inputPrazoProtesto = document.all("' + prazoProtestoName + '");');
	eval('this.inputIof = document.all("' + iofName + '");');
	eval('this.inputJuros = document.all("' + jurosName + '");');
	eval('this.inputMulta = document.all("' + multaName + '");');
	eval('this.inputValorDesconto1 = document.all("' + valorDesconto1Name + '");');
	eval('this.inputValorDesconto2 = document.all("' + valorDesconto2Name + '");');
	eval('this.inputValorDesconto3 = document.all("' + valorDesconto3Name + '");');
	eval('this.inputObservacao = document.all("' + observacaoName + '");');
	eval('this.inputObservacaoText = document.all("' + observacaoText + '");');

	// armazene o número máximo de linhas permitidas e o número de caracteres por linha
	this.maxLinhasPermitidas = numeroLinhas;
	this.caracteresPorLinha = numeroColunas;
	// armazene o código de uma quebra de página
	this.crlf = String.fromCharCode(13) + String.fromCharCode(10);
	
	// armazene a mensagem de erro
	this.msgErro = msgErro;
	
	// crie as funções private dessa classe - não devem ser usadas fora dessa classe
	this.CalculeLinhasDisponiveis = CalculeLinhasDisponiveis;
	this.InformeLinhasDisponiveis = InformeLinhasDisponiveis;
	this.FormateTexto = FormateTexto;
	this.setText = SetText;
	this.ValideObservacao = ValideObservacao;
	this.BloqueieEvento = BloqueieEvento;

	// determine a função que valida o campo da observação
	this.onBlur = OnBlurObservacao;
	
	// inicialize o número de linhas disponíveis - esse número não leva em conta o que já está
	// digitado no campo observação
	this.linhasDisponiveis = -1;
	
	// acrescente um método à classe string, que será usado na mensagem de erro
	String.prototype.FillIn = FillIn;
}


//*************************************************************************************************************
/**
@name BloqueieEvento
@description Impede que o usuário digite no campo quando não restar mais espaço
@return Não retorna nada
@author Jorge Bittencourt
*/
function BloqueieEvento()
{
	// se não houver mais espaço para o usuário digitar caracteres, não permita mais que
	// ele digite nada
	if (this.InformeLinhasDisponiveis() == 0)
	{
		// eu bloqueie porque se o usuário digitar o número máximo de linhas incompletas e depois tentar escrever
		// mais algumas coisas nas linhas que ele já possui, esse bloqueio impede o usuário
		//event.returnValue = false;
	}
}


//*************************************************************************************************************
/**
@name CalculeLinhasDisponiveis
@description Calcula o número de linhas disponíveis para o usuário digitar informações
@created 12/05/2004
@return O número de linhas disponíveis
@author Jorge Bittencourt
*/
function CalculeLinhasDisponiveis()
{
	// só faça os cálculos abaixo se o valor de this.linhasDisponiveis já não tiver sido
	// calculado depois do último foco - isso aumenta a performance quando essa função é
	// chamada em cada keyUp para calcular dinamicamente as linhas disponíveis
	
	if (this.linhasDisponiveis == -1)
	{
		// determine quais dos campos estão vazios - para cada campo não-vazio, diminua em 1
		// o número de linhas disponíveis
		this.linhasDisponiveis = this.maxLinhasPermitidas;
		if (this.inputAbatimento != null && this.inputAbatimento.value != "")
			this.linhasDisponiveis--;
		if (this.inputPrazoProtesto != null && this.inputPrazoProtesto.value != "")
			this.linhasDisponiveis--;
		if (this.inputIof != null && this.inputIof.value != "")
			this.linhasDisponiveis--;
		if (this.inputJuros != null && this.inputJuros.value != "")
			this.linhasDisponiveis--;
		if (this.inputMulta != null && this.inputMulta.value != "")
			this.linhasDisponiveis--;
		if (this.inputValorDesconto1 != null && this.inputValorDesconto1.value != "")
			this.linhasDisponiveis--;
		if (this.inputValorDesconto2 != null && this.inputValorDesconto2.value != "")
			this.linhasDisponiveis--;
		if (this.inputValorDesconto3 != null && this.inputValorDesconto3.value != "")
			this.linhasDisponiveis--;
	}
	// retorne o resultado
	return this.linhasDisponiveis;
}


//*************************************************************************************************************
/**
@name FormateTexto
@description Formata o texto do campo Observação à medida que o usuário digita ou quando faz copy
 e paste. As palavras podem ser quebradas no meio, por isso é de responsabilidade do usuário de
 digitar Enters. De qualquer forma, o que o usuário vir na tela será gravado no banco de dados.
@created 19/05/2004
@return Não retorna nada
@author Jorge Bittencourt
*/
function FormateTexto()
{
	// uma array com as linhas digitadas
	linhasPreenchidas = this.inputObservacao.value.split(this.crlf);
	
	// o resultado, que consiste no texto digitado pelo usuário formatado
	var resultado = "";
	
	// determina se o texto digitado pelo usuário sofreu formatação
	var modificado = false;
	
	// itere por cada linha
	for (i = 0; i < linhasPreenchidas.length; i++)
	{	
		// se a linha tiver comprimento maior que o permitido, quebre-a em quantas linhas forem necessárias
		// para não ultrapassar o limite de caracteres por linha
		if (linhasPreenchidas[i].length > this.caracteresPorLinha)
		{
			// o texto original foi formatado
			modificado = true;

			// o próximo loop é necessário porque, quando o usuário faz um copy paste, 
			// o texto colado pode ter o equivalente a várias linhas, que precisam ser
			// quebradas com quebras de line
			
			// o texto original será examinado pedaço por pedaço, cada um não excedendo o
			// comprimento da linha da observação
			var resto, pedaco;
			
			// inicialize o primeiro pedaço e o resto
			pedaco = linhasPreenchidas[i].substr(0, this.caracteresPorLinha);
			resto = linhasPreenchidas[i].substr(this.caracteresPorLinha);
			
			// itere enquanto houver pedaços
			while (pedaco.length > 0)
			{
				// acrescente o pedaço ao resultado - se houver mais pedaços depois, acrescente
				// uma quebra de página também
				resultado += pedaco + (resto.length > 0 ? this.crlf : "");
				
				// pegue o próximo pedaço
				pedaco = resto.substr(0, this.caracteresPorLinha);
				// atualize o resto do texto
				resto = resto.substr(this.caracteresPorLinha);
			}
		}
		// se a linha tiver comprimento ok, simplesmente adicione-a ao resultado
		else
			resultado += linhasPreenchidas[i];
		
		// a não ser que essa seja a última linha, acrescente uma quebra de página, já que estes
		// foram tirados no split acima
		if (i != linhasPreenchidas.length - 1)
			resultado += this.crlf;
	}
	
	// se o texto foi formatado, exiba-o no campo observação
	if (modificado)
	{
		this.inputObservacao.value = resultado;
	}
	// atualize o número de linhas disponíveis
	this.InformeLinhasDisponiveis();
}


//*************************************************************************************************************
/**
@name InformeLinhasDisponiveis
@description Informe ao usuário o número de linhas disponíveis quando o campo Observação
 receber foco
@created 12/05/2004
@return o número de linhas disponíveis
@author Jorge Bittencourt
*/
function InformeLinhasDisponiveis()
{
	// calcule o número de linhas disponíveis 
	var linhasDisponiveis = this.CalculeLinhasDisponiveis();
	// calcule o número de linhas que já estão preenchidas no campo observação
	var linhasPreenchidas = this.inputObservacao.value.split(this.crlf);	
	
	// em duas situações eu não decremento o número de linhas preenchidas - o que equivale a 
	// adicionar 1 ao número de linhas disponíveis:
	// quando o usuário ainda não digitou todas as linhas e a última linha onde ele está digitando
	// não está cheia ainda ou quando o usuário já digitou mais linhas do que ele pode e a última
	// linha permitida já está cheia
	if (linhasPreenchidas[linhasPreenchidas.length - 1].length == this.caracteresPorLinha ||
		(linhasPreenchidas.length >= this.maxLinhasPermitidas && linhasPreenchidas[this.maxLinhasPermitidas - 1].length == this.caracteresPorLinha))
		numeroLinhasPreenchidas = linhasPreenchidas.length;
	else
		numeroLinhasPreenchidas = linhasPreenchidas.length - 1;
	
	if (linhasDisponiveis-numeroLinhasPreenchidas<=0)
	{
		// informe o número de linhas excedidas.
		this.inputObservacaoText.innerText = "Total de linhas excedidas: " + (numeroLinhasPreenchidas-linhasDisponiveis+1);
	}
	else
	{
		// avise ao usuário o número de linhas disponíveis
		this.inputObservacaoText.innerText = "Linhas disponíveis para preenchimento: " + (linhasDisponiveis - numeroLinhasPreenchidas);
	}
	
	return linhasDisponiveis - numeroLinhasPreenchidas;
}


//*************************************************************************************************************
/**
@name OnBlurObservacao
@description Remove o aviso de linhas disponíveis e valida o campo de observação
@created 02/06/2004
@return Não retorna nada
@author Jorge Bittencourt
*/
function OnBlurObservacao()
{
	// valide a observação
	this.ValideObservacao();
	
	// remova o texto que informa o número de linhas que estão disponíveis no campo de observação
	// isso é feito para que a tela não mostre informações inconsistentes a respeito do número de
	// linhas disponíveis. Por exemplo, o usuário termina de digitar 2 linhas e ainda tem 7 disponíveis
	// Aí ele preenche o campo de juros, por exemplo. Ou eu faço o número de linhas disponíveis mudar ou
	// o seu valor ficará inconsistente. A melhor solução é só exibir o número de linhas disponíveis enquanto
	// o campo de observação tiver o foco
	this.inputObservacaoText.innerText = "";
	
	// invalide o número de linhas disponíveis
	this.linhasDisponiveis = -1;
}


//*************************************************************************************************************
/**
@name SetText
@description Muda o texto do campo Observação
@created 20/05/2004
@param text: o texto a ser exibido no campo
@return Não retorna nada
@author Jorge Bittencourt
*/
function SetText(text)
{
	this.inputObservacao.value = text;
}


//*************************************************************************************************************
/**
@name ValideObservacao
@description Valide o texto da observação - assuma que o texto já está corretamente formatado
@created 12/05/2004
@return true, se a validação tiver sucesso, false, caso contrário
@author Jorge Bittencourt
*/
function ValideObservacao()
{
	// por causa de algum tipo de bug, quando o campo está vazio, mesmo assim o split abaixo
	// produz uma linha - deveria produzir 0. Por causa disso, teste, como caso especial, se
	// o campo de observação está vazio
	if (this.inputObservacao.value != "")
	{
		var linhas = this.inputObservacao.value.split(this.crlf);
		var linhasDisponiveis = this.CalculeLinhasDisponiveis();
		if (linhas.length > linhasDisponiveis)
		{
			alert(this.msgErro.FillIn(new Array((new Number(linhas.length)).toString(), 
					(new Number(linhasDisponiveis)).toString(), 
					(new Number(this.maxLinhasPermitidas)).toString(), 
					(new Number(this.caracteresPorLinha)).toString())));
			this.mostreLinhasDisponiveis = false;
			this.inputObservacao.select();
			return false;
		}
		else
		{
			this.mostreLinhasDisponiveis = true;
			return true;
		}	
	}
	// se o campo de observação estiver vazio, a validação tem sucesso
	return true;
}
