//--------------------------------------------------------------------------------
// Loan class. 
//--------------------------------------------------------------------------------
// Dependencies:
// DateHelpers.js
//--------------------------------------------------------------------------------
// This class calculate the tenor instalment details for the given loan amount, 
// interest rate, total tenors, booking date and loan cycle.
//--------------------------------------------------------------------------------
function Loan( pLoanAmount, pInterestRate, pTenor, pBookingDate, pLoanCycle, pDaysInYear )
{
    // Public properties.
    this.Amount         = pLoanAmount;
    this.InterestRate   = pInterestRate;
    this.Tenor          = pTenor;
    this.BookingDate    = pBookingDate;
    this.LoanCycle      = pLoanCycle;
    this.DaysInYear     = pDaysInYear;
    // Calculated public details.
    this.TotalInstalmentAmount;
    this.TotalInterestAmount;
    this.TotalPrincipalAmount;
    this.InstalmentListAmount;
    this.PrincipalListAmount;
    this.InterestListAmount;
    this.BalanceListAmount;
    this.StartDateList;
    this.EndDateList;
    this.StatementDateList;
    this.DaysInCycle;
    
    // This object.
    var me = this;
    
    //--------------------------------------------------------------------------------
    // Constructor.
    //--------------------------------------------------------------------------------
    init(); function init()
    {
        // Initialize public properties.
        me.TotalInstalmentAmount    = 0.00;
        me.TotalInterestAmount      = 0.00;
        me.TotalPrincipalAmount     = 0.00;
        me.InstalmentListAmount     = new Array( pTenor );
        me.PrincipalListAmount      = new Array( pTenor );
        me.InterestListAmount       = new Array( pTenor );
        me.BalanceListAmount        = new Array( pTenor );
        me.StartDateList            = new Array( pTenor );
        me.EndDateList              = new Array( pTenor );
        me.StatementDateList        = new Array( pTenor );
        me.DaysInCycle              = new Array( pTenor );
        
        // Calculate the loan details.
        calculateLoanDetails( pLoanAmount, pInterestRate, pTenor, pBookingDate, pLoanCycle, pDaysInYear );
    }
    
    
    //--------------------------------------------------------------------------------
    // Private methods.
    //--------------------------------------------------------------------------------
    // This method calculate the tenor instalment details for the given loan amount, 
    // interest rate, total tenors, booking date and loan cycle.
    function calculateLoanDetails( pLoanAmount, pInterestRate, pTenor, pBookingDate, pLoanCycle, pDaysInYear )
    {
        // Prepare required details for calculation.
        var arrTenorNumber      = new Array( pTenor );
        var arrDaysInMonth      = new Array( pTenor );
        
        // 1. Order tenor number from 1 to given tenor.
        for( var index = 0; index < pTenor; index++ )
            arrTenorNumber[index] = index + 1; // Start tenor from 1.
        
        // 2. Calculate number of days for each month based on 
        // the start date and end date.
        var startDate = pBookingDate;
        // Calculate end date based on the loan cycle (one day prior to the loan cycle date).
        var endDate = ( pBookingDate.getDate() < pLoanCycle ) ? 
                      getDate( pBookingDate.getFullYear(), pBookingDate.getMonth()+1, pLoanCycle-1 ) : 
                      getDate( pBookingDate.getFullYear(), pBookingDate.getMonth()+2, pLoanCycle-1 );
        // Loop through each tenor and calculate the number of days 
        // of the tenor.
        var tempDate = null;
        for( var tenor in arrTenorNumber )
        {
            // Get and update days in month.
            arrDaysInMonth[tenor] = dateDiff( endDate, startDate ) + 1;
            
            // Update in the global variables.
            // Days in cycle list.
            me.DaysInCycle[tenor]   = arrDaysInMonth[tenor];
            // 1. Start date list.
            tempDate                = new Date( startDate ); 
            me.StartDateList[tenor] = tempDate.getDate() + '-' + getMonthName(tempDate.getMonth()+1) + '-' + tempDate.getFullYear();
            // 2. End date list.
            tempDate                = new Date( endDate ); 
            me.EndDateList[tenor]   = tempDate.getDate() + '-' + getMonthName(tempDate.getMonth()+1) + '-' + tempDate.getFullYear();
            // 3. Statement days list.
            me.StatementDateList[tenor] = pLoanCycle + '-' + getMonthName(tempDate.getMonth()+1) + '-' + tempDate.getFullYear();
            
            // Move dates to next month, by setting end date as start date 
            // and add 1 month to end date.
            startDate = addDay( endDate, 1 ).toString();
            endDate = addMonth( endDate, 1 );
        }
        
        // Calculate master values.
        var _EMI            = parseFloat( getEMI( pLoanAmount, pInterestRate, pTenor ) ); // Calculate emi.
        var _perDay         = 1 / pDaysInYear;
        var _baseInterest   = _perDay * ( pInterestRate / 100 );
        var balance         = pLoanAmount;
        
        // Helpers.
        var instalment      = 0.00;
        var interest        = 0.00;
        var principal       = 0.00;
        
        // Loop through the tenors to calculate balance, principal and interest.
        for( var tenor in arrTenorNumber )
        {
            // 1.Calulate interest for the tenor based on days in the month.
            interest = balance * ( arrDaysInMonth[tenor] * _baseInterest );
            
            // 2. Calculate instalment and principal.
            // Normal tenor.
            if( arrTenorNumber[tenor] < pTenor )
            {
                instalment = _EMI; // Keep EMI as instalment.
                principal = instalment - interest;
            }
            else // Final tenor. So, carry forward all previous details.
            {
                // Calculate principal and instalment.
                principal = balance;
                instalment = principal + interest;
            }
                
            // 3. Calculate the balance amount.
            balance -= principal;
            
            // Update in the public properties.
            me.InstalmentListAmount[tenor]    = instalment.toFixed(2);
            me.InterestListAmount[tenor]      = interest.toFixed(2);
            me.PrincipalListAmount[tenor]     = principal.toFixed(2);
            me.BalanceListAmount[tenor]       = balance.toFixed(2);
            // Calcualte totals.
            me.TotalInstalmentAmount  += parseFloat( instalment );
            me.TotalPrincipalAmount   += parseFloat( principal );
            me.TotalInterestAmount    += parseFloat( interest );
        }
        
        // Round the values.
        me.TotalInstalmentAmount = me.TotalInstalmentAmount.toFixed(2);
        me.TotalInterestAmount   = me.TotalInterestAmount.toFixed(2);
        me.TotalPrincipalAmount  = me.TotalPrincipalAmount.toFixed(2);
    }

    // This method calculate the EMI based on the given
    // loan amount, interest rate, tenure.
    function getEMI( pLoanAmount, pInterestRate, pTenure )
    {
        // Get the values.
        var loanAmount = pLoanAmount;
	    var interestRate = pInterestRate;
	    var tenure = pTenure;

	    // Calculation helpers.
	    var r = 0; // Rate of interest per month.
	    var n = 0; // Total number of periods.
	    var p = 0; // Principal.
	    var EMI = 0; // EMI.
	    var pow = 0; // Temporary variable used for the calculation.

	    p = loanAmount;
	    r = ( interestRate / 12 ) / 100;
	    n = tenure;
	    pow = Math.pow( ( 1 + r ), n );
	    EMI = p * r * ( pow / ( pow -1 ) );

	    // Return the calculated EMI.
	    return EMI.toFixed( 2 );
    }
}
