package com.fitbank.installment;

import java.math.BigDecimal;

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

/**
 * Clase que se encarga de generar tabla de amortización con cuota fija de
 * capital.
 * 
 * @author Soft Warehouse S.A.
 */
public class CapitalFixInterestDistributedInstallment extends AbstractQuota {

    @Override
    public void calculate(final InstallmentTable pQuotaTable) throws Exception {
        this.quotaTable = pQuotaTable;
        this.quotanumber = pQuotaTable.getBegincalculationperiod();
        this.reducedcapital = pQuotaTable.getAmount();
        boolean end = false;
        // Obtiene la moneda de la tabla de pagos
        final Tcurrencyid tcurrencyid = FinancialHelper.getInstance()
                .getTcurrencyid(this.quotaTable.getCurrency());
        // Define el total de cuotas de capital de la tabla de pagos
        final int totalCapitalPeriod = this.quotaTable.getTotalperiod();
        if (this.quotaTable.getGraceperiod() > 0) {
            throw new FitbankException("QUO009",
                    "TABLA DE CAPITAL NO PERMITE CUOTAS DE GRACIA");
        }
        // Obtiene el valor fijo de capital de cada cuota.
        final BigDecimal capital = this.quotaTable.getAmount().divide(
                new BigDecimal(totalCapitalPeriod),
                tcurrencyid.getNumerodecimales(), BigDecimal.ROUND_HALF_UP);
        // Genera las cuotas con Gracia de Capital.
        this.generateGrace();
        super.calculateTotalperiod(pQuotaTable);
        // Genera las cuotas de capital e interés.
        for (int i = this.quotaTable.getBegincalculationperiod(); i <= this.quotaTable
                .getTotalperiod(); i++) {
            super.calculatePayDate(this.quotaTable);
            if (i == this.quotaTable.getTotalperiod()) {
                end = true;
            }
            this.processByCategory(false);
            this.calculateCuota(capital, end);
            this.quotanumber++;
            if (super.stop) {
                break;
            }
        }// end for
    }

    /**
     * Calcula tabla de pago dado una cuota fija.
     * 
     * @throws Exception
     */
    private void calculateCuota(BigDecimal pCapital, final boolean pEnd)
            throws Exception {
        // Si se trata de la última cuota.
        if (pEnd) {
            // Carga todo el capital reducido al capital de la cuota.
            pCapital = this.reducedcapital;
            this.reducedcapital = this.reducedcapital.subtract(pCapital);
        }
        super.addQuota(this.quotanumber, this.reducedcapital, pCapital, true);
        if (!pEnd) {
            this.reducedcapital = this.reducedcapital.subtract(pCapital);
        }
    }

    /**
     * Genera cuotas de interés por el número de periodos de gracia definidos
     * para la tabla.
     * 
     * @throws Exception
     */
    private void generateGrace() throws Exception {
        if (this.quotaTable.getGraceperiod() > 0) {
            final BigDecimal capital = Constant.BD_ZERO;
            for (int i = 0; i < this.quotaTable.getGraceperiod(); i++) {
                super.calculatePayDate(this.quotaTable);
                super.processByCategory(false);
                super.addQuota(this.quotanumber, this.reducedcapital, capital,
                        true);
                this.quotanumber++;
            }
        }
    }
}
