/********
Author: David Fernandes
MEC: 496324
Date: July 2009
*********/

/*
NOTA: sempre que se coloca um valor no slide, este invoca as funcoes de alteracao (change).
*/

//variaveis globais suporte ao fluxo

//variaveis que definem que operacao esta a occorrer
var lockSlidePrazo;
var lockSlideRentabilidade;
var lockSlideRendaProgramada;
var lockSlideRendaVitalicia;
var lockSlideCapital;

var intervaloCapitalInico;
var intervaloCapitalFim;

var CapitalAUtilizar;

var alteracaoIdadeRendaVitalicia = false;

//data no servidor - array: [dia, mes, ano]
var dataServidor = null;

//INITIALIZE: funcoes responsaveis por inicializar toda a logica da pagina
function initialize() {
    initFieldsDefaultHTML();
    obtemDataServidor();
    preencheCombosData(dataServidor[2]);
    initializeSlides();
}

/****** Inicializa os sliders***************/
function initializeSlides(){

    intervaloCapitalInico = valorCapitalMinimo;
    intervaloCapitalFim = valorCapitalMaximo;

    inicializeCapitalSlide('hCapital', 'sCapital', geraCapitalValuesSlide(valorCapitalMinimo, valorCapitalMaximo, valorCapitalSaltoSlide, valorCaptialOmissao), valorCapitalMinimo, valorCapitalMaximo, updateSliderCapital, changeSliderCapital);
    inicializePrazoSlide('hPrazo', 'sPrazo', valorPrazoMinimo, valorPrazoMaximo, updateSliderPrazo, changeSliderPrazo);
    inicializeRentabilidadeSlide('hRentabilidade', 'sRentabilidade', valorRentabilidadeMinimo, valorRentabilidadeMaximo, updateSliderRentabilidade, changeSliderRentabilidade);
    inicializeRendaProgramadaSlide('hRendaProgramada', 'sRendaProgramada', valorRendaProgramadaMinimo, valorRendaProgramadaMaximo, updateSliderRendaProgramada, changeSliderRendaProgramada);
    inicializeRendaVitaliciaSlide('hRendaVitalicia', 'sRendaVitalicia', valorRendaVitaliciaMinimo, valorRendaVitaliciaMaximo, updateSliderRendaVitalicia, changeSliderRendaVitalicia);

    //Hack: reniciamos os sliders das rendas tendo em conta o capital
    alteraValoresIntervaloRendaProgramada(valorCapitalMinimo, valorCapitalMaximo);
    alteraValoresIntervaloRendaVitalicia(valorCapitalMinimo, valorCapitalMaximo);
    
    //A ordem e IMPORTANTE
    insereValorSlideCapital(valorCaptialOmissao);
    insereValorSlidePrazo(valorPrazoOmissao);
    insereValorSlideRentabilidade(valorRentabilidadeOmissao);
    
    //não alterei o valor por omissão porque provocava valores negativos quando se mexia no slider
    //não procurei a causa. Desta forma não causa erros.
    rentabilidade.setValue(4);
}


/********Controladores dos sliders************/

//On Slide
function updateSliderCapital(piValor) {
    $('capitalvalor').value = add_commas(getNearestMultiple(piValor, 1) + "") + ",00";
}

function updateSliderPrazo(piValor) {
    $('prazovalor').innerHTML = getNearestMultiple(piValor, 1);
}

function updateSliderRentabilidade(piValor) {
    $('rentabilidadevalor').innerHTML = getNearestMultiple(piValor, 1);
}

function updateSliderRendaProgramada(piValor) {
    $('RendaProgramadavalor').innerHTML = add_commas(roundNumber(piValor, 2) + "");
}

function updateSliderRendaVitalicia(piValor) {
    $('RendaVitaliciavalor').innerHTML = add_commas(roundNumber(piValor, 2) + "");
    $('euroSymbolRendaVitalicia').innerHTML = $('euroSymbolForJavascript').innerHTML + "&nbsp;";
}

//mensagens no HTML
function rendaVitaliciaMensagemHtml() {
    $('RendaVitaliciavalor').innerHTML = mensagemRendaVitaliciaAbaixoDoMinimo;
    $('euroSymbolRendaVitalicia').innerHTML = "";
}

//On change
function changeSliderCapital(piValor) {
    var rendaVitaliciaAbaixoMinimo = false;
    
    updateSliderCapital(piValor);

    lockSlideCapital = true;


    var idadeAnos = devolveAnosEntreDatas(new Array($('dia').value, $('mes').value, $('ano').value),
	                                dataServidor);
	                                

    if (!lockSlideRendaProgramada && !lockSlideRendaVitalicia) {

        var rendaVitalicia = devolveNovaRendaVitalicia();

        if (rendaVitalicia < valorRendaVitaliciaMinimoDosMiminos) {
            //alert("Renda vitalicia abaixo do valor mínimo " + $('euroSymbolForJavascript').innerHTML + valorRendaVitaliciaMinimoDosMiminos + ".");
            rendaVitalicia = valorRendaVitaliciaMinimoDosMiminos;
            rendaVitaliciaAbaixoMinimo = true;
        }

        var rendaProgramada = devolveNovaRendaProgramada();

        insereValorSlideRendaVitalicia(rendaVitalicia);

        insereValorSlideRendaProgramada(rendaProgramada);
    
        //coloca-se primeiro o valor minimo para fazer recuar o slider
        if (rendaVitaliciaAbaixoMinimo) rendaVitaliciaMensagemHtml();

    } else {
    if (lockSlideRendaProgramada) {
            //HACK: coloca valor do capital
            $('capitalvalor').value = add_commas(CapitalAUtilizar + "") + ",00";
            //HACK: recalcula o valor do rendaProgramada e insere sem update no slider
            updateSliderRendaProgramada(devolveNovaRendaProgramada());
            
            var rendaVitalicia = devolveNovaRendaVitalicia();

            if (rendaVitalicia < valorRendaVitaliciaMinimoDosMiminos) {
                //alert("Renda vitalicia abaixo do valor mínimo " + $('euroSymbolForJavascript').innerHTML + valorRendaVitaliciaMinimoDosMiminos + ".");
                rendaVitalicia = valorRendaVitaliciaMinimoDosMiminos;
                rendaVitaliciaAbaixoMinimo = true;
            }

            insereValorSlideRendaVitalicia(rendaVitalicia);

            //coloca-se primeiro o valor minimo para fazer recuar o slider
            if (rendaVitaliciaAbaixoMinimo) rendaVitaliciaMensagemHtml();
            
        } else {
            //HACK: coloca valor do capital
            $('capitalvalor').value = add_commas(CapitalAUtilizar + "") + ",00";
            //HACK: recalcula o valor do rendaVitalicia e insere sem update no slider
            updateSliderRendaVitalicia(devolveNovaRendaVitalicia());
            
            var rendaProgramada = devolveNovaRendaProgramada();
            insereValorSlideRendaProgramada(rendaProgramada);

        }
    }
    
    lockSlideCapital = false;
}

function changeSliderRendaProgramada(piValor) {
    updateSliderRendaProgramada(piValor);
    valorFinalInsere();
    
    if (lockSlidePrazo || lockSlideRentabilidade || lockSlideCapital) return;

    lockSlideRendaProgramada = true;

    var capital = devolveCapitalAlteradoNovaRendaProgramada();
    CapitalAUtilizar = roundNumber(capital, 0); 
    insereValorSlideCapital(capital);

    valorFinalInsere();
    
    if ((capital < intervaloCapitalInico) || (capital > intervaloCapitalFim)) {
        alteraValoresIntervaloCapital();
    }
    
    
    lockSlideRendaProgramada = false;
}

function changeSliderRendaVitalicia(piValor) {
    updateSliderRendaVitalicia(piValor);

    if (lockSlideCapital || alteracaoIdadeRendaVitalicia) return;

    lockSlideRendaVitalicia = true;

    var capital = devolveCapitalAlteradoNovaRendaVitalicia();
    CapitalAUtilizar = roundNumber(capital, 0);
    
    insereValorSlideCapital(capital);

    if ((capital < intervaloCapitalInico) || (capital > intervaloCapitalFim)) {
        alteraValoresIntervaloCapital();
    }

    lockSlideRendaVitalicia = false;
}

function changeSliderPrazo(piValor) {
    updateSliderPrazo(piValor);

    lockSlidePrazo = true;

    //os presupostos dos intervalos do prazo mudaram: renda Programada e o seu intervalo tambem tem de mudar
    alteraValoresIntervaloRendaProgramada(intervaloCapitalInico, intervaloCapitalFim);
    
    var renda = devolveNovaRendaProgramada();
    insereValorSlideRendaProgramada(renda);
    
    lockSlidePrazo = false;
}

function changeSliderRentabilidade(piValor) {
    updateSliderRentabilidade(piValor);

    lockSlideRentabilidade = true;

    valorFinalInsere();

    lockSlideRentabilidade = false;
}

function valorFinalInsere() {
    var valorFinal = valorFinalCalculo(retira_commas($("capitalvalor").value), $("rentabilidadevalor").innerHTML * 0.01, $("prazovalor").innerHTML, retira_commas($("RendaProgramadavalor").innerHTML));
    $('valorfinal').innerHTML = add_commas(roundNumber(valorFinal, 2) + "");
}

/******* Invocacao das formulas de calculo ********/

function devolveNovaRendaProgramada() {
    
	var valor = calculaRendaProgramada(valorRentabilidadeOmissao * 0.01, retira_commas($("capitalvalor").value), $("prazovalor").innerHTML);
    
	return valor;
}

function devolveCapitalAlteradoNovaRendaProgramada() {

    var rendaProgramada = getNearestMultiple(retira_commas($("RendaProgramadavalor").innerHTML), 1);

    //var valor = calculaCapitalAlteracaoRendaProgramada($("rentabilidadevalor").innerHTML * 0.01, rendaProgramada, $("prazovalor").innerHTML);
    var valor = calculaCapitalAlteracaoRendaProgramada(valorRentabilidadeOmissao * 0.01, rendaProgramada, $("prazovalor").innerHTML);
    
    return valor;
}

function devolveNovaRendaVitalicia() {

    var idadeAnos = devolveAnosEntreDatas(new Array($('dia').value, $('mes').value, $('ano').value),
	                                dataServidor);
    
    var valor = calculaRendaVitalicia(retira_commas($("capitalvalor").value), dadosRendaVitalicia[idadeAnos], valorRentabilidadeRendaVitaliciaComparacaoConstante);

    return valor;
}

function devolveCapitalAlteradoNovaRendaVitalicia() {

    var rendaVitalicia = getNearestMultiple(retira_commas($("RendaVitaliciavalor").innerHTML), 1);
    
    var idadeAnos = devolveAnosEntreDatas(new Array($('dia').value, $('mes').value, $('ano').value),
	                                dataServidor);

    var valor = calculaCapitalAlteracaoRendaVitalicia(rendaVitalicia, dadosRendaVitalicia[idadeAnos], valorRentabilidadeRendaVitaliciaComparacaoConstante);

    return valor;
}

/*********** Controladores HTML - alteracoes provocam alteracoes nos slides ************/

//Novo intervalo para o capital
//Retorna false se limite do capital ultrapassa o minimo ou o maximo estabelecido
//Retorna true se tudo se correu bem
function alteraValoresIntervaloCapital() {
    var novoValor = retira_commas($("capitalvalor").value);

    //retira possiveis virgulas inseridas pelo utilizador
    var x = novoValor.split('.');
    novoValor = x[0];
    
    var inicio, fim;
    var flagRetorno = true;

    //retirar possiveos casas decimais
    novoValor = getNearestMultiple(novoValor, 1);

    //verificar se o valor nao ultrapassa os limites estabelecidos
    if (novoValor > valorCapitalMaximaValorCalcularAmplitudeSlide) {
        alert("O capital máximo aceitável é " + $('euroSymbolForJavascript').innerHTML + valorCapitalMaximaValorCalcularAmplitudeSlide + ".");
        flagRetorno = false;
        
        $("capitalvalor").value = add_commas(valorCapitalMaximaValorCalcularAmplitudeSlide + "") + ",00";
        
        novoValor = valorCapitalMaximaValorCalcularAmplitudeSlide;
    }

    if (novoValor < valorCapitalMinimo) {
    //        alert("O capital mínimo aceitável é " + $('euroSymbolForJavascript').innerHTML + valorCapitalMinimo + ".");
        flagRetorno = false;
        
        $("capitalvalor").value = add_commas(valorCapitalMinimo + "") + ",00";

        novoValor = valorCapitalMinimo;
    }

    //calcular amplitudes com o novoValor
    inicio = novoValor - (valorCapitalAmplitudeSlide / 2);
    fim = novoValor + (valorCapitalAmplitudeSlide / 2);

    inicio = getNearestMultiple(inicio, 1);
    fim = getNearestMultiple(fim, 1);

    //verifica se esta dentro dos limites aceitaveis para o intervalo
    if (inicio < valorCapitalMinimo) {
        //valores standarts
        inicio = valorCapitalMinimo;
        fim = valorCapitalMaximo;
    } else {
        if (fim > valorCapitalMaximaValorCalcularAmplitudeSlide) {

            //valores standarts - perspectiva maxima
            inicio = valorCapitalMaximaValorCalcularAmplitudeSlide - valorCapitalAmplitudeSlide;
            fim = valorCapitalMaximaValorCalcularAmplitudeSlide;
        }

    }

    //novo capital, implica novos intervalos para as rendas - estas funcoes nao inserem valores nos sliders
    alteraValoresIntervaloRendaProgramada(inicio, fim);
    alteraValoresIntervaloRendaVitalicia(inicio, fim);

    //novos valores capital
    intervaloCapitalInico = inicio;
    intervaloCapitalFim = fim;
    
    finalizaSliderCapital();
    inicializeCapitalSlide('hCapital', 'sCapital', geraCapitalValuesSlide(inicio, fim, valorCapitalSaltoSlide, novoValor), inicio, fim, updateSliderCapital, changeSliderCapital);

    CapitalAUtilizar = novoValor;
    insereValorSlideCapital(novoValor);
    
    return flagRetorno;
}


//reinicializa novo slider de RendaProgramada sem inserir valores: responsabilidade de quem evocou funcao
function alteraValoresIntervaloRendaProgramada(initCapital, fimCapital) {
    //var inicioIntervalo = calculaRendaProgramada($("rentabilidadevalor").innerHTML * 0.01, initCapital, $("prazovalor").innerHTML);
    //var fimIntervalo = calculaRendaProgramada($("rentabilidadevalor").innerHTML * 0.01, fimCapital, $("prazovalor").innerHTML);
    var inicioIntervalo = calculaRendaProgramada(valorRentabilidadeOmissao * 0.01, initCapital, $("prazovalor").innerHTML);
    var fimIntervalo = calculaRendaProgramada(valorRentabilidadeOmissao * 0.01, fimCapital, $("prazovalor").innerHTML);


    finalizaSliderRendaProgramada();
    inicializeRendaProgramadaSlide('hRendaProgramada', 'sRendaProgramada', inicioIntervalo, fimIntervalo, updateSliderRendaProgramada, changeSliderRendaProgramada);    
}

//reinicializa novo slider de RendaVitalicia sem inserir valores: responsabilidade de quem evocou funcao
function alteraValoresIntervaloRendaVitalicia(initCapital, fimCapital) {
    var idadeAnos = devolveAnosEntreDatas(new Array($('dia').value, $('mes').value, $('ano').value),
	                                dataServidor);

    var inicioIntervalo = calculaRendaVitalicia(initCapital, dadosRendaVitalicia[idadeAnos], valorRentabilidadeRendaVitaliciaComparacaoConstante);
    var fimIntervalo = calculaRendaVitalicia(fimCapital, dadosRendaVitalicia[idadeAnos], valorRentabilidadeRendaVitaliciaComparacaoConstante);


    if (inicioIntervalo < valorRendaVitaliciaMinimoDosMiminos)
        inicioIntervalo = valorRendaVitaliciaMinimoDosMiminos;

    finalizaSliderRendaVitalicia();

    inicializeRendaVitaliciaSlide('hRendaVitalicia', 'sRendaVitalicia', inicioIntervalo, fimIntervalo, updateSliderRendaVitalicia, changeSliderRendaVitalicia);
}

//mudanca idade de nascimento - altera rendaVitalicia
function listenerIdadeMudanca() {
    var rendaVitaliciaAbaixoMinimo = false;
    
    if ((isDate($('ano').value, $('mes').value, $('dia').value) == false) || (verificaIdadeInput() == false)) {
        //reset para data "inicial"
        $('dia').selectedIndex = 0;
        $('mes').selectedIndex = 0;
        $('ano').selectedIndex = Math.round((limiteIdadeSuperior - limiteIdadeInferior) / 2);
    }

    alteraValoresIntervaloRendaVitalicia(intervaloCapitalInico, intervaloCapitalFim);

    var rendaVitalicia = devolveNovaRendaVitalicia();

    if (rendaVitalicia < valorRendaVitaliciaMinimoDosMiminos) {
    //    alert("Renda vitalicia abaixo do valor mínimo " + $('euroSymbolForJavascript').innerHTML + valorRendaVitaliciaMinimoDosMiminos + ".");
        rendaVitalicia = valorRendaVitaliciaMinimoDosMiminos;
        rendaVitaliciaAbaixoMinimo = true;
    }
    
    alteracaoIdadeRendaVitalicia = true;
    insereValorSlideRendaVitalicia(rendaVitalicia);
    alteracaoIdadeRendaVitalicia = false;

    if (rendaVitaliciaAbaixoMinimo) rendaVitaliciaMensagemHtml();
}

/******** Conteudo HTML **************/
//coloca valores por defeito em todas as posicoes para valores incializados quando das contas
function initFieldsDefaultHTML() {
    $('capitalvalor').value = add_commas(valorCaptialOmissao + "") + ",00";
    $('RendaProgramadavalor').innerHTML = valorRendaProgramadaOmissao;
    $('RendaVitaliciavalor').innerHTML = valorRendaVitaliciaOmissao;
    $('prazovalor').innerHTML = valorPrazoOmissao;
    $('rentabilidadevalor').innerHTML = valorRentabilidadeOmissao;
}


//preenche combos anos nascimento
function preencheCombosData(ano) {
    var diasData = $('dia');
    var mesesData = $('mes');
    var anosData = $('ano');

    for (var i = 1, j = 0; i < 32; i++, j++) {
        diasData.options[j] = new Option(i, i);
    }

    for (var i = 1, j = 0; i <= mesesPT.length; i++, j++) {
        mesesData.options[j] = new Option(mesesPT[i - 1], i);
    }

    for (var i = (ano - limiteIdadeSuperior), j = 0; i < ((ano - limiteIdadeInferior) + 1); i++, j++) {
        anosData.options[j] = new Option(i, i);
    }

    $('dia').selectedIndex = 0;
    $('mes').selectedIndex = 0;
    $('ano').selectedIndex = Math.round((limiteIdadeSuperior - limiteIdadeInferior) / 2) + 8;
}



//verifica a Idade e o seu limite - aquando da mudanca de idade
function verificaIdadeInput() {

    var idadeAnos = devolveAnosEntreDatas(new Array($('dia').value, $('mes').value, $('ano').value),
	                                dataServidor);

    if (idadeAnos < limiteIdadeInferior) {
        alert("Ainda não completou " + limiteIdadeInferior + " anos. Não poderá subscrever este produto.");
        return false;
    }

    if (idadeAnos > limiteIdadeSuperior) {
        alert("Idade máxima para subscrição: inferior a " + limiteIdadeSuperior + " anos.");
        return false;
    }

    return true;
}

//obtem data do servidor
function obtemDataServidor() {

    var entradas = $('dataServidor').innerHTML.split("-");

    dataServidor = new Array(parseInt(entradas[0]),parseInt(entradas[1]), parseInt(entradas[2]));
}

//compara duas datas (actual e data nascimento) e devolve idade em anos
//argumentos com array[dia, mes, ano]
function devolveAnosEntreDatas(dataAnos, dataActual) {
    
    //Cria Objectos Date
    var dataActualDate = new Date();
    dataActualDate.setYear(dataActual[2]);
    dataActualDate.setMonth(dataActual[1]);
    dataActualDate.setDate(dataActual[0]);

    var dataAnosDate = new Date();
    dataAnosDate.setYear(dataAnos[2]);
    dataAnosDate.setMonth(dataAnos[1]);
    dataAnosDate.setDate(dataAnos[0]);

    // The number of milliseconds in one day
    var ONE_DAY = 1000 * 60 * 60 * 24

    // Convert both dates to milliseconds
    var date1_ms = dataActualDate.getTime();
    var date2_ms = dataAnosDate.getTime();

    // Calculate the difference in milliseconds
    var difference_ms = Math.abs(date1_ms - date2_ms);

    // Convert back to days and return
    var diasEntreDatas = Math.round(difference_ms / ONE_DAY);

    //formula excel: SIMULADOR - BPI RENDAS VITALÍCIAS - CCmpleto.xls
    var anos = ((diasEntreDatas / 365.25) + 0.5);

    //no excel o arredondamento nao respeita a regra dos 0.5
    var arredonda = "" + anos;
    arredonda = arredonda.split(".")[0];

    //alert(arredonda);
    return arredonda;
}

//valida data
function isDate(y, m, d) {
    var date = new Date(y, m - 1, d);
    var convertedDate = "" + date.getFullYear() + (date.getMonth() + 1) + date.getDate();
    var givenDate = "" + y + m + d;

    if (givenDate == convertedDate) {
        return true;
    } else {
        alert("A data inserida não existe.");
        return false; 
    }
}

//gera array valores possiveis para a combo do capital
function geraCapitalValuesSlide(inicio, fim, salto, omissao) {
   
    var values = new Array();
    var i, flagValorOmissao = false;

    for (i = inicio; i <= fim; i += salto) {
        
        if (i == omissao) flagValorOmissao = true;   
    
        values.push(i);
    }

    if (!flagValorOmissao) values.push(omissao);

    if (i > fim) values.push(fim);

    return values;
}

//Suport MATH functions
function getNearestMultiple(piValue, piMultiple){
	return Math.round(piValue / piMultiple) * piMultiple;
}

function roundNumber(num, dec) {
    return num.toFixed(dec);
}


function add_commas(nStr){
   nStr += '';
   
   x = nStr.split('.');
   
   x1 = x[0];
   x2 = x.length > 1 ? '.' + x[1] : '';
   
   var rgx = /(\d+)(\d{3})/;
   
   while (rgx.test(x1)) {
    x1 = x1.replace(rgx, '$1' + ',' + '$2');
  }
    
  //notacao -  1,444,444.33
  retornar = x1 + x2;
  
  retornar = retornar.replace(".", "#");
  retornar = retornar.replace(/,/g, ".");
  retornar = retornar.replace("#", ",");

  return retornar;
}

function retira_commas(str) {
    str = str.replace(/\./g, "");
    str = str.replace(",", ".");
    return str;
}

//Bugg Correction
function buggyNothing(variavel) {
}
