//GE Calculator
function GECalculator_GetMonthlyPayment(FinancedAmount, DownPaymentPeriod, MonthlyPaymentRef, TotalFinancingCostRef, EffectiveInterestRateRef, TotalFinancingCostAfterTaxRef)
{
	GECalculator_CalculateByPeriod(FinancedAmount, DownPaymentPeriod, GECalculator_MonthlyInterestRate, GECalculator_MonthlyFee, GECalculator_PercentageDeductionAfterTax, MonthlyPaymentRef, TotalFinancingCostRef, EffectiveInterestRateRef, TotalFinancingCostAfterTaxRef);
}

function GECalculator_GetPayOffPeriod(FinancedAmount, MonthlyPayment, DownPaymentPeriodRef, TotalFinancingCostRef, EffectiveInterestRateRef, TotalFinancingCostAfterTaxRef)
{
	GECalculator_CalculateByPayment(FinancedAmount, MonthlyPayment, GECalculator_MonthlyInterestRate, GECalculator_MonthlyFee, GECalculator_PercentageDeductionAfterTax, GECalculator_MinMonths, GECalculator_MaxMonths, DownPaymentPeriodRef, TotalFinancingCostRef, EffectiveInterestRateRef, TotalFinancingCostAfterTaxRef);
}

function GECalculator_CalculateByPeriod(LoanAmount, NumberOfMonths, MonthlyRate, MonthlyFee, PercentageDeductionAfterTax, MonthlyPaymentRef, TotalFinancingCostRef, EffectiveInterestRateRef, TotalFinancingCostAfterTaxRef)
{
	var MonthlyPayment = GECalculator_CalculateMonthlyPayment(LoanAmount, NumberOfMonths, MonthlyRate, MonthlyFee);
	var PaymentPlanPayment = GECalculator_CreatepaymentPlanPayment(MonthlyPayment, NumberOfMonths);
	var PaymentPlanPeriod = GECalculator_CreatepaymentPlanPeriod(NumberOfMonths);
   	var TotalPayment = GECalculator_CalculateTotalPayment(MonthlyPayment, NumberOfMonths, PaymentPlanPayment, PaymentPlanPeriod);
	var FinancingCost = TotalPayment - LoanAmount;
	var InternalInterest = GECalculator_CalculateInternalInterest(MonthlyPayment, NumberOfMonths, LoanAmount, PaymentPlanPayment, PaymentPlanPeriod);
	var FinancingCostAfterTax = GECalculator_FinancingCostAfterTax(FinancingCost, PercentageDeductionAfterTax);

	MonthlyPaymentRef[0] = GECalculator_FormatToCurrency(Math.ceil(MonthlyPayment))
	TotalFinancingCostRef[0] = GECalculator_FormatToCurrency(Math.ceil((FinancingCost + LoanAmount)));
	EffectiveInterestRateRef[0] = (InternalInterest*100).toFixed(2);
	TotalFinancingCostAfterTaxRef[0] = GECalculator_FormatToCurrency(Math.ceil(FinancingCostAfterTax));
}

function GECalculator_CalculateByPayment(LoanAmount, WantedMonthlyPayment, MonthlyRate, MonthlyFee, PercentageDeductionAfterTax, MinMonths, MaxMonths, DownPaymentPeriodRef, TotalFinancingCostRef, EffectiveInterestRateRef, TotalFinancingCostAfterTaxRef)
{
	var NumberOfMonths = GECalculator_CalculateNumberOfMonths(LoanAmount, MonthlyRate, MonthlyFee, MinMonths, MaxMonths, WantedMonthlyPayment);
	var Balance = LoanAmount;
	Balance = GECalculator_CalculateBalance(Balance, LoanAmount, NumberOfMonths -1, WantedMonthlyPayment, MonthlyRate, MonthlyFee);
	Balance = GECalculator_CalculateBalance(Balance, LoanAmount, 1, 0, MonthlyRate, MonthlyFee);
	var PaymentPlanPayment = GECalculator_CreatepaymentPlanPayment2(WantedMonthlyPayment, NumberOfMonths, Balance);
	var PaymentPlanPeriod = GECalculator_CreatepaymentPlanPeriod2(NumberOfMonths);
	var InternalInterest = GECalculator_CalculateInternalInterest(WantedMonthlyPayment, NumberOfMonths, LoanAmount, PaymentPlanPayment, PaymentPlanPeriod);
    var TotalPayment = GECalculator_CalculateTotalPayment(WantedMonthlyPayment, NumberOfMonths, PaymentPlanPayment, PaymentPlanPeriod);
	var FinancingCost = TotalPayment - LoanAmount;
	var FinancingCostAfterTax = GECalculator_FinancingCostAfterTax(FinancingCost, PercentageDeductionAfterTax);

	DownPaymentPeriodRef[0] = NumberOfMonths;
	TotalFinancingCostRef[0] = GECalculator_FormatToCurrency(Math.ceil((FinancingCost + LoanAmount)));
	EffectiveInterestRateRef[0] = (InternalInterest*100).toFixed(2);
	TotalFinancingCostAfterTaxRef[0] = GECalculator_FormatToCurrency(Math.ceil(FinancingCostAfterTax));
}

function GECalculator_GetMaxPeriod(FinancedAmount)
{
	return GECalculator_CalculateMaximumMonths(FinancedAmount, GECalculator_MonthlyInterestRate, GECalculator_MonthlyFee, GECalculator_MinMonths, GECalculator_MaxMonths, GECalculator_PercentageCreditLimit, GECalculator_MinMonthlyPayment);
}

function GECalculator_CalculateMaximumMonths(LoanAmount, MonthlyRate, MonthlyFee, MinMonths, MaxMonths, PercentageCreditLimit, MinMonthlyPayment)
{
	var MinPayment = GECalculator_CalculateMinimumPayment(LoanAmount, MonthlyRate, MonthlyFee, MinMonths, MaxMonths, PercentageCreditLimit, MinMonthlyPayment);
		
	var intMonths = MaxMonths;
	while (intMonths > MinMonths)
	{
		var MonthlyPayment = GECalculator_CalculateMonthlyPayment(LoanAmount, intMonths, MonthlyRate, MonthlyFee);
		if (!isNaN(MonthlyPayment))
		{
			if (MonthlyPayment >= MinPayment)
			{
				return intMonths;
			}
		}
		intMonths -= 1;
	}
	return 0;
}

function GECalculator_CalculateMinimumPayment(LoanAmount, MonthlyRate, MonthlyFee, MinMonths, MaxMonths, PercentageCreditLimit, MinMonthlyPayment)
{
	var CalculatedMin = GECalculator_CalculateMonthlyPayment(LoanAmount, MaxMonths, MonthlyRate, MonthlyFee);
	var PercentageMin = PercentageCreditLimit * LoanAmount;
	return Math.max(CalculatedMin, Math.max(MinMonthlyPayment, PercentageMin));
}

function GECalculator_CalculateNumberOfMonths(LoanAmount, MonthlyRate, MonthlyFee, MinMonths, MaxMonths, WantedMonthlyPayment)
{
	var intMonths = MinMonths;
	while (intMonths <= MaxMonths)
	{
		var MonthlyPayment = GECalculator_CalculateMonthlyPayment(LoanAmount, intMonths, MonthlyRate, MonthlyFee);
	    if (MonthlyPayment < WantedMonthlyPayment)
	    {
			return intMonths;
		}
		intMonths += 1;
	}
	return 2147483647;
}

function GECalculator_CalculateBalance(Balance, LoanAmount, NumberOfMonths, WantedMonthlyPayment, MonthlyRate, MonthlyFee)
{
	var intCurrentPeriod = 0;
	var Loan = Balance;
	while (intCurrentPeriod < NumberOfMonths)
	{
		Loan *= (1 + MonthlyRate);
		if (Loan > 1000)
		{
			Loan += MonthlyFee;
		}
		Loan -= WantedMonthlyPayment;
		intCurrentPeriod += 1;
	}
	return Loan;
}

function GECalculator_CreatepaymentPlanPayment(MonthlyAmount, NumberOfMonths)
{
	var PaymentPlanPayment = new Array();
	var I = 0;
	var x = 0;
	var periods = NumberOfMonths;
	
	while (periods > 0)
	{
		PaymentPlanPayment[I] = MonthlyAmount;
		I += 1;
		periods -= 1;
	}
	return PaymentPlanPayment;
}

function GECalculator_CreatepaymentPlanPayment2(WantedMonthlyPayment, NumberOfMonths, Balance)
{
	var PaymentPlanPayment = new Array();

	for (I=0;I<(NumberOfMonths-1);I++)
	{
		PaymentPlanPayment[I] = WantedMonthlyPayment;
	}
	PaymentPlanPayment[NumberOfMonths-1] = Balance;
	return PaymentPlanPayment;
}

function GECalculator_CreatepaymentPlanPeriod(NumberOfMonths)
{
	var PaymentPlanPeriod = new Array();
	var I = 0;
	var x = 0;
	var periods = NumberOfMonths;
	
	while (periods > 0)
	{
		PaymentPlanPeriod[I] = periods;
		I += 1;
		periods -= 1;
	}
	return PaymentPlanPeriod;
}

function GECalculator_CreatepaymentPlanPeriod2(NumberOfMonths)
{
	var PaymentPlanPeriod = new Array();

	for (I=0;I<(NumberOfMonths-1);I++)
	{
		PaymentPlanPeriod[I] = I+1;
	}
	PaymentPlanPeriod[NumberOfMonths-1] = NumberOfMonths;
	return PaymentPlanPeriod;
}

function GECalculator_CalculateInternalInterest(MonthlyAmount, NumberOfMonths, LoanAmount, PaymentPlanPayment, PaymentPlanPeriod)
{
	var dblRate = 0.5;
	var dblRateModifier = dblRate;
	var dblPresentValue = 0;

	while (Math.abs(dblPresentValue - LoanAmount) > 0.001)
	{
		while (dblPresentValue < LoanAmount)
		{
            dblRate = (dblRate + (dblRateModifier * -1));

			var dblSum = 0;
			for (x=0;x<NumberOfMonths;x++)
			{
				dblSum += (PaymentPlanPayment[x] / Math.pow((1 + dblRate), PaymentPlanPeriod[x]));
			}
			dblPresentValue = dblSum;
		}
		dblRateModifier = dblRateModifier / 2;
	
		while (dblPresentValue > LoanAmount)
		{
            dblRate = (dblRate + dblRateModifier);

			var dblSum = 0;
			for (x=0;x<NumberOfMonths;x++)
			{
				dblSum += (PaymentPlanPayment[x] / Math.pow((1 + dblRate), PaymentPlanPeriod[x]));
			}
			dblPresentValue = dblSum;
		}
		dblRateModifier = dblRateModifier / 2;
	}

	return GECalculator_ToAnual(dblRate);
}

function GECalculator_ToAnual(Rate)
{
	return (Math.pow((1 + Rate), 12) - 1);
}

function GECalculator_CalculateTotalPayment(MonthlyAmount, NumberOfMonths, PaymentPlanPayment, PaymentPlanPeriod)
{

	var dblSum = 0;
	for (x=0;x<NumberOfMonths;x++)
	{
		dblSum += PaymentPlanPayment[x];
	}

	return dblSum;
}

function GECalculator_CalculateMonthlyPayment(LoanAmount, NumberOfMonths, MonthlyRate, MonthlyFee)
{
	var dblA = GECalculator_CalculateA(LoanAmount, MonthlyRate, MonthlyFee, NumberOfMonths);
	var intU = GECalculator_CalculateU(LoanAmount, MonthlyRate, MonthlyFee, NumberOfMonths, dblA);
	var dblTreshold = GECalculator_CalculateTreshold(MonthlyRate, NumberOfMonths, intU, MonthlyFee);

	if (LoanAmount <= dblTreshold)
	{
		return GECalculator_CalculateP(LoanAmount, MonthlyRate, MonthlyFee, intU, NumberOfMonths);
	}
	else
	{
		return GECalculator_CalculateP(LoanAmount, MonthlyRate, MonthlyFee, intU, -1);
	}
}
function GECalculator_CalculateA(LoanAmount, MonthlyInterestRate, MonthlyFee, NumberOfMonths)
{
	var dblSmallerPeriodicInterestForMonths = GECalculator_CalculateSmallerPeriodicInterest(MonthlyInterestRate, NumberOfMonths);
	var dblLargerPeriodicInterestForMonths = GECalculator_CalculateLargerPeriodicInterest(MonthlyInterestRate, NumberOfMonths);

	return LoanAmount - 1001 * dblSmallerPeriodicInterestForMonths + MonthlyFee * dblLargerPeriodicInterestForMonths / (MonthlyInterestRate * (1 + MonthlyInterestRate));
}

function GECalculator_CalculateSmallerPeriodicInterest(MonthlyInterestRate, NumberOfMonths)
{
	return 1 - Math.pow(1 + MonthlyInterestRate, -NumberOfMonths);
}       

function GECalculator_CalculateLargerPeriodicInterest(MonthlyInterestRate, NumberOfMonths)
{
	return 1 + Math.pow(1 + MonthlyInterestRate, -NumberOfMonths + 1);
}       

function GECalculator_CalculateU(LoanAmount, MonthlyInterestRate, MonthlyFee, NumberOfMonths, a)
{
	var dblFirstNominator = GECalculator_CalculateFirstNominatorPartOfU(MonthlyInterestRate, MonthlyFee);
    var dblSecondNominator = GECalculator_CalculateSecondNominatorPartOfU(LoanAmount, MonthlyInterestRate, a, MonthlyFee, NumberOfMonths);
    var dblDenominator = GECalculator_CalculateDenominatorPartOfU(MonthlyInterestRate);
    var dblU = (dblFirstNominator - dblSecondNominator) / dblDenominator;
	return Math.floor(dblU);
}       

function GECalculator_CalculateFirstNominatorPartOfU(MonthlyInterestRate, MonthlyFee)
{
	return log10(2.0 * MonthlyFee / MonthlyInterestRate);
}       

function GECalculator_CalculateSecondNominatorPartOfU(LoanAmount, MonthlyInterestRate, a, MonthlyFee, NumberOfMonths)
{
	return log10(a - Math.sqrt(Math.pow(a, 2) - (4 * MonthlyFee / MonthlyInterestRate) * (LoanAmount + (MonthlyFee / MonthlyInterestRate)) * Math.pow(1 + MonthlyInterestRate, -NumberOfMonths - 1)));
}

function GECalculator_CalculateDenominatorPartOfU(MonthlyInterestRate)
{
	return log10((1 + MonthlyInterestRate));
}

function GECalculator_CalculateTreshold(MonthlyInterestRate, NumberOfMonths, u, MonthlyFee)
{
	var dblSmallerPeriodicInterestForMonths  = GECalculator_CalculateSmallerPeriodicInterest(MonthlyInterestRate, NumberOfMonths);
	var dblSmallerPeriodicInterestForMonthsAndU = GECalculator_CalculateSmallerPeriodicInterest(MonthlyInterestRate, (NumberOfMonths - u));
	var dblSmallerPeriodicInterestForU = GECalculator_CalculateSmallerPeriodicInterest(MonthlyInterestRate, u);
	return 1001 * dblSmallerPeriodicInterestForMonths / dblSmallerPeriodicInterestForMonthsAndU - (MonthlyFee / MonthlyInterestRate) * dblSmallerPeriodicInterestForU;
}

function GECalculator_CalculateP(LoanAmount, MonthlyInterestRate, MonthlyFee, u, NumberOfMonths)
{
	var dblSmallerPeriodicInterestForU = GECalculator_CalculateSmallerPeriodicInterest(MonthlyInterestRate, u);

	if (NumberOfMonths < 0)
	{
		return MonthlyInterestRate * (LoanAmount - 1001 * Math.pow(1 + MonthlyInterestRate, -u)) / dblSmallerPeriodicInterestForU + MonthlyFee;
	}
	else
	{
		var dblSmallerPeriodicInterestForMonths = GECalculator_CalculateSmallerPeriodicInterest(MonthlyInterestRate, NumberOfMonths);
		return (MonthlyInterestRate * LoanAmount + MonthlyFee * dblSmallerPeriodicInterestForU) / dblSmallerPeriodicInterestForMonths;
	}
}

function GECalculator_FinancingCostAfterTax(FinancingCost, PercentageDeductionAfterTax)
{
	return (FinancingCost * (1 - PercentageDeductionAfterTax));
}

function log10(x)
{
	return Math.log(x)/Math.log(10);
}

function GECalculator_FormatToCurrency(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');
	}
	return x1 + x2 + ',-';
}
