package com.fitbank.installment;

import java.math.BigDecimal;

import com.fitbank.common.helper.CalculationBase;
import com.fitbank.common.helper.Constant;
import com.fitbank.fin.helper.FinancialHelper;
import com.fitbank.hb.persistence.gene.Tcurrencyid;

/**
 * Calcuo de cuota fija.
 * @author BANTEC Inc
 * @version 2.0
 */
public class FixedInstallment {
  /**
   * Base de calculo.
   */
  private CalculationBase calculationBase = null;
  
  //Crea una instancia
  /**
   * Crea un nuevo objeto.
   */
  public FixedInstallment(CalculationBase pCalculationBase){
    this.calculationBase = pCalculationBase;
  }
  
  /**
   * Calcula cuota fija de una tabla de amortizacion. 
   * @param pAmount        Capital original.
   * @param pRate          Tasa.
   * @param pDaysperquota  Numero de dias por cuota.
   * @param totalquotas    Numero de periodos o cuotas.
   * @return
   * @throws Exception
   */
  public BigDecimal calculate(BigDecimal pAmount,BigDecimal pRate, BigDecimal pFixedValue, int pDaysperquota,int totalquotas,String pCurrency) throws Exception{
    Tcurrencyid  tcurrencyid = FinancialHelper.getInstance().getTcurrencyid(pCurrency);
    BigDecimal quotavalue = BigDecimal.ZERO;
    BigDecimal one = BigDecimal.ONE;
    //pr = rate of period
    BigDecimal pr = this.getRateofperiodIV(pRate,pDaysperquota);
    BigDecimal prplusone = null;
    prplusone = one.add(pr);
    //quotavalue = k*(rateofperiod/((1-(1+rateofperiod)^(-totalquotas)))
    //i  = 1/(prplusone^totalquotas)
    //quotavalue = k*(rateofperiod/i)
    BigDecimal i = one.divide(prplusone.pow(totalquotas),12,BigDecimal.ROUND_HALF_UP);
    i = one.subtract(i);
    quotavalue = pAmount.multiply(pr.divide(i,12,BigDecimal.ROUND_HALF_UP)) ;
    quotavalue = quotavalue.divide(BigDecimal.ONE,tcurrencyid.getNumerodecimales(),BigDecimal.ROUND_HALF_UP);
    quotavalue = quotavalue.add(pFixedValue);
    return quotavalue;
  }
  
  /**
   * Entrega la tasa del periodo. 
   * @param pRate
   * @param pDaysperquota
   * @return
   * @throws Exception
   */
  public BigDecimal getRateofperiodIV(BigDecimal pRate,int pDaysperquota) throws Exception{
	double rate = (pRate.doubleValue() / 100 ) * pDaysperquota / calculationBase.getYearBase();
	return BigDecimal.valueOf(rate).divide(Constant.BD_ONE,6,BigDecimal.ROUND_HALF_UP);
  }
  

	/**
	 * Metodo que calcula el valor de la cuota fiaja con interes anticipado. 
	 * @throws Exception
	 */
	public BigDecimal calculateIA(BigDecimal pAmount,BigDecimal pRate, int pDaysperquota,int totalquotas,String pCurrency) throws Exception {
		BigDecimal quotaValue = null;
		double rate = this.getRateofperiodIA(pRate, pDaysperquota);
		//formula Cuota = K/((1-(1-i)^p)/i) 
		Tcurrencyid  tcurrencyid = FinancialHelper.getInstance().getTcurrencyid(pCurrency);
		//(1-i)^p
		double aux = (1 - rate);
		aux = Math.pow(aux, totalquotas);
		//(1-(1-i)^p)/i
		aux = (1 - aux ) / rate ;
		//K/((1-(1-i)^p)/i) 
		quotaValue = pAmount.divide(BigDecimal.valueOf(aux), tcurrencyid.getNumerodecimales(), BigDecimal.ROUND_HALF_UP);
		return quotaValue;
	}
	
  /**
   * Entrega la tasa del periodo. 
   * @param pRate
   * @param pDaysperquota
   * @return
   * @throws Exception
   */
  public double getRateofperiodIA(BigDecimal pRate,int pDaysperquota) throws Exception{
	double rate = (pRate.doubleValue() / 100 ) * pDaysperquota / calculationBase.getYearBase();
	rate = rate / (1+rate);		
	BigDecimal rateAI = BigDecimal.valueOf(rate).divide(Constant.BD_ONE, 6, BigDecimal.ROUND_HALF_UP);
	return rateAI.doubleValue();
  }
}
