//------------------------------------------------------------------------------
//   $Id: mortgage.js,v 1.6 2003/11/26 15:36:09 soglesby Exp $
//   $Source: /bbsrc/web/docs/us/jscommon/calculators/mortgage.js,v $
//   $Revision: 1.6 $
//------------------------------------------------------------------------------

function Mortgage(p)
{
	//Set up default values 
	this.principal = p; 	// Loan principal
	this.rate = 4.75;					// Interest rate expressed as %
	this.period = 30;				// Loan period in years
	this.points = 0;				// Points (if any)
	this.mnthlypayment = monthlyPayment(this.principal, 12, this.rate, this.period * 12);
	this.startdate = generateStartDate();
	this.prepayamt = 0;
	//this.prepayfreq = 'month';
	this.prepaystrt = generateStartDate();
	this.proceeds = this.principal;
	this.eff_rate = this.rate;
	this.amortize = false;
	this.width = "100%";
	
	this.set = MortgageValueSet;
	this.calculate = MortgageCalculate;
	this.showAmortization = MortgageShowAmortization;
	this.putMtgeInfo = MortgagePutMtgeInfo;
	this.compareTotals = MortgageCompareTotals;
	this.setWidth = MortgageSetWidth;
	//this.print = MtgeCalcPrintResult;
}

function MortgageSetWidth(w)
{
	this.width = w;
}

function generateStartDate()
{
	var d = new Date();
	var obj = new Object();
	obj.month = d.getMonth();
	obj.year = d.getYear();

	if (obj.year < 1000)
		obj.year += 1900;
		
	return obj;
}

function MortgageValueSet(obj)
{
	var fld = obj.name;
	var val = obj.value;

	//alert("val= "+ val+ "\nfld= "+fld);
	if (val == null)
		val = obj[obj.selectedIndex].value;

	if (typeof(val) == "string")
	{
		/* strip out any commas from the value */
		val = val.replace(/,/g, "");
	}
	
	if (fld == 'amortize')
	{
		this.amortize = obj.checked;
		return true;
	}
	else if (fld == 'prepayfreq')
	{
		this.prepayfreq = val;
		return true;
	}
	
	if (val == "")
		val = 0;

	if (isNaN(val) || val < 0)
	{
		alert('You must enter a positive numeric value in this field');
		obj.focus();
		return false;
	}
	
	if ((fld == 'rate' || fld == 'period') && val <= 0)
	{
		alert('Value must be greater than 0');
		obj.focus();
		return false;
	}
	if ((fld == 'rate') && val > 29)
	{
		alert('Interest Rate: Value must be less than 29');
		obj.focus();
		return false;
	}
	if ((fld == 'period') && val > 99)
	{
		alert('Loan Period: Value must be less than 99');
		obj.focus();
		return false;
	}
	if ((fld == 'points') && val > 12)
	{
		alert('Points: Value must be less than 12');
		obj.focus();
		return false;
	}
	switch (fld)
	{
	case 'principal':
	    if (val != 0)
		this.mnthlypayment = '';
	    else
		return true;
	    break;
	case 'mnthlypayment':
	    if (val != 0)
		this.principal = '';
	    else
		return true;
	    break;
	case 'start_month':
		this.startdate.month = val;
		return true;
	case 'start_year':
		this.startdate.year = val;
		return true;
	case 'ppm_month':
		this.prepaystrt.month = val;
		//alert("case-prepay-month= " + val);
		return;
	case 'ppm_year':
		this.prepaystrt.year = val;
		return;
	}
	
	this[fld] = val;
}

function MortgageCalculate()
{
	var points = Number(this.points); 	//convert/force to a integer;
	if (this.principal == ""){
	 	this.principal = calcAmortPrincipal(this.mnthlypayment, 12, this.rate, this.period * 12);
	}
	else{
	 	this.mnthlypayment = monthlyPayment(this.principal, 12, this.rate, this.period * 12);
	}
	this.proceeds = this.principal * (1 - (points / 100));
	

	this.eff_rate = calculateEffRate(this.mnthlypayment, this.proceeds, this.period);
}

function calculateEffRate(payment, amount, period){
//Calculate the effective rate, solution by Newton-Raphson Method

	var ee=0.01
	var X=0;
	var MAXGUESSES=100;
	var min_rate=.01;
	var max_rate=.2;
	var tmp1=0;
	var rate=0;
	var solution;
	
	for (var ii=0; ii<MAXGUESSES; ii++) {
		rate=min_rate + (max_rate - min_rate)/2;
		mon_rate=rate/12;
		tmp1=mon_rate*amount/(1-Math.pow(1+mon_rate,-1*period*12));
		X=payment - tmp1;
		if (X < 0){
			max_rate=rate;
		}else{
			min_rate=rate;
		}
		if (Math.abs(X) < ee) break;
	}
	solution = Math.round(rate*100000)/1000;
	return solution;
}


function MortgageShowAmortization()
{
    var principal = this.principal;
	var payment = Number(this.mnthlypayment);
	var interest = this.rate / 12 / 100;
	var periods = this.period * 12;
	var month = Number(this.startdate.month) + 1;
	var year = this.startdate.year;
	var beg_year = year;
	var end_year = year + this.period;
	var ppm_amount = this.prepayamt;
	var ppm_month = this.prepaystrt.month;
	//alert("prepaystrt.month= " + ppm_month);
	var ppm_year = this.prepaystrt.year;
	var ppm_freq = this.prepayfreq;
    var towardsPrincipal = new Object();
    var towardsInterest = new Object();
	var additionalPayment = new Array(periods);
	var paymentArray = new Object();
    var col_period = "";
    var col_payment = "";
    var col_interest = "";
    var col_principal = "";
    var year_payments = "";
	var body = "";
	var termpayments = 0;
	var terminterest = 0;
	var termprincipal = 0;
		
    var title = '<TR>'
			 +     '<TD COLSPAN="4" class="bg4">'
			 +        '<span class="hlite">Annualized Mortgage Payments</span>'
			 +     '</TD>'
			 +  '</TR>';
	var header = '<TR class="bg2">'
			 +	   '<TD ALIGN="left">'
			 +        '<b>Period</b>'
			 +     '</TD>'
			 +     '<TD ALIGN="right">'
			 +        '<b>Payments</b>'
			 +     '</TD>'
			 +	   '<TD ALIGN="right">'
			 +        '<b>Interest<b/>'
			 +     '</TD>'
			 +     '<TD ALIGN="right">'
			 +        '<b>Principal</b>'
			 +     '</TD>'
			 +   '</TR>'; 

	// set up prepayments
	// if the prepayments start on, before or after the mortgage, 
	// return an alert to the user.
	if (ppm_amount != ""){
	//alert("year="+ year + "\nmonth=" + this.startdate.month + "\nppm_month=" + ppm_month + "\nppm_year=" + ppm_year);
            // ppm_month = month;
             //ppm_year = year;
             if (ppm_year < year) {
               	alert("Please enter a Prepayment Start Date that is later than the Loan State Date.");
             	return "";
			 }
			 
			if ((ppm_year == year) && (Number(ppm_month) <= this.startdate.month)){
			 	alert("Please enter a Prepayment Start Date that is later than the Loan State Date.");
             	return "";
			 }
			
			if (ppm_year >  (year + this.period)) {
				alert("Please enter a Prepayment Start Date that is later than the Loan State Date.");
             	return "";
			}
				
			
    }
		

	var a = new Object();
	var b = new Object();
	var c = new Object();
	
	// calculate the number of months without prepayment
	if (month == 12) 
	{
		month = 0;
		year++; beg_year++;
	}

	var tempmonth = month;
	var tmpstart=0;
	
	for (j = 0; j < periods; j++) {
		if ((year == ppm_year) && (tempmonth == ppm_month)) {
			break;
		}
		a[j] = payment;
		c[j] = principal * interest;
		b[j] = a[j] - c[j];
		principal = principal - b[j];
		termpayments += Number(a[j]);
		terminterest += c[j];
		termprincipal += b[j];
		paymentArray[year] = a;
		towardsPrincipal[year] = b;
		towardsInterest[year] = c;
		
		if (++tempmonth > 11) {
			tempmonth = 0;
			a = new Object();
			b = new Object();
			c = new Object();
			year++;
		}
		//alert("temp-month-endloop=  "+tempmonth +"j=" +j);
		
	}
	//set tmpstart to the last position of j
	//the next loop will start at this position
	tmpstart=j;

	// finish with prepayment, if any 
	var last = false;
	var temp_prepay;
	var first;
	if (ppm_month == 11){
		first = true;
	}
	else{
		first = false;
	}
	for (j = tmpstart; j < periods && !(last); j++) {
	    if (principal > payment) {
			if (ppm_freq == "year") {
				if (first || ((j % 12) == ppm_month)){
					//alert("j=" + j + "ppm_month=" + ppm_month);
					temp_prepay = Number(ppm_amount);
					first=false;
				}
				else{
					temp_prepay = 0;
				}
			}
			else{
				temp_prepay = Number(ppm_amount);
			}
			a[j] = payment + temp_prepay;
			c[j] = principal * interest;
			b[j] = a[j] - c[j];
			
			principal = principal - b[j];
			if (principal < 0){
				payment = payment + principal;
				a[j] = a[j] + principal; 
				b[j] = b[j] + principal;
				last = true;
			}
	    } 
		else {
			c[j] = principal * interest;
			a[j] = principal + c[j];
			b[j] = a[j] - c[j];
			principal = 0;
			last = true;
	    }
		termpayments += Number(a[j]);
	    terminterest += c[j];
	    termprincipal += b[j];
	    paymentArray[year] = a;
	    towardsPrincipal[year] = b;
	    towardsInterest[year] = c;
	    if (++tempmonth > 11) {
		a = new Object();
		b = new Object();
		c = new Object();
		year++;
		tempmonth = 0;
	    } 
		
	}
		
		
	year = beg_year;
        var totalInterest = 0;
        var totalPrincipal = 0;
        var year_payments = 0;
		var monthcount = 0;
		var datarows = '';
		var points = Number(this.points);
		if (points){
			year_payments =  this.principal * (points / 100);
			totalInterest = this.principal * (points / 100);
			var had_pts = true;
		}
        for (i in paymentArray) {
		  for (j in paymentArray[i]) {
                totalInterest += Number(towardsInterest[i][j]);
                totalPrincipal += Number(towardsPrincipal[i][j]);
                year_payments += Number(paymentArray[i][j]);
				if (month < 12) month++;
				monthcount++;
           }
		    //alert("loop-month= " + month +"\nmonthcount= "+monthcount);
           datarows += '<TR><TD>' 
				+ 12 + "/" + year + '</TD><TD ALIGN="right">&euro;' 
				+ toCurrency(year_payments) 
				+ '</TD><TD ALIGN="right">&euro;' 
				+ toCurrency(totalInterest) + '</TD><TD ALIGN="right">&euro;' 
				+ toCurrency(totalPrincipal) 
				+ '</TD></TR>';
           	year_payments = 0;
           	totalInterest = 0;
           	totalPrincipal = 0;
           	month = 0;
           	year++;
		   	if (had_pts) {
				year_payments = 0;  //reset the payments
				totalInterest = 0;
				had_pts = false;	//reset flag
		  	}
        }

        var totals = '<TR><TD COLSPAN="4"><HR></TD>'
			+ '</TR><TR><TD>'
			+ 'Totals:</TD><TD ALIGN="right">&euro;' + toCurrency(termpayments) 
			+ '</TD><TD ALIGN="right">&euro;' 
			+ toCurrency(terminterest) + '</TD><TD ALIGN="right">&euro;' 
			+ toCurrency(termprincipal) 
			+ '</TD></TR><TR><TD COLSPAN="4">'
			+ '</TD></TR>';
	var prepaymt_results = this.compareTotals(termpayments, monthcount);
	var table = '<TABLE cellpadding="3" cellspacing="1" BORDER="0" class="bg5" width="100%">' 
			+ title + prepaymt_results + header + datarows + totals + '</TABLE>';
	return (table);

}

function MortgageCompareTotals(reported, mcount) {
	var principal = this.principal;
    var payment = Number(this.mnthlypayment);
    var interest = this.rate / 12 / 100;
  	var periods = this.period * 12;
	var diffamount = 0;
	var diffterm = 0;
	var results;

	diffamount = (payment * periods) - reported;
	//alert( "mcount= " + mcount + "\n" + "payment= " + payment + "\n" + "periods= " + periods + "\n" + "reported= " + reported + "\n" + "diffamount= " + diffamount + "\n");
	if (diffamount > 1) {
		diffterm = periods - mcount;
		results = '<TR>'
				+ '<TD COLSPAN="4" ALIGN="left">'
				+ '<br>'
				+ 'Prepayments in the amount of ' + toCurrency(this.prepayamt) 
				+ ' will result in a reduction of total<br>'
				+ 'interest by &euro;' + toCurrency(diffamount) 
				+ '. The term of the loan will be reduced by ' 
				+ Math.floor(diffterm / 12) + ' years<br>and ' 
				+ (diffterm % 12) + ' months. <br><br></TD></TR>';
		return (results);
	} 
	else {
		return ('');
	}
} 

function PopulateForm(frm)
{
		// populate form with values contained/calculated by mtgecalc object 
		frm.principal.value = toCurrency(mtgecalc.principal);
		frm.rate.value = mtgecalc.rate;
		frm.mnthlypayment.value = toCurrency(mtgecalc.mnthlypayment);
		frm.period.value = mtgecalc.period;
		frm.points.value = mtgecalc.points;
		frm.start_month.selectedIndex = Number(mtgecalc.startdate.month);
		//BuildMonthDropDown(frm.start_month, mtgecalc.startdate.month);
		frm.start_year.value = mtgecalc.startdate.year;
		
		//initialize prepayment info
		//BuildPrepayDropDown(frm.prepayfreq, mtgecalc.prepayfreq);
		if (mtgecalc.prepayfreq == 'year') frm.prepayfreq.selectedIndex = 1;
		//BuildMonthDropDown(frm.ppm_month, mtgecalc.prepaystrt.month);
		frm.ppm_month.selectedIndex = Number(mtgecalc.prepaystrt.month);
		//alert("start-ppm-month=  "+frm.ppm_month.value);
		frm.prepayamt.value = mtgecalc.prepayamt;
		frm.ppm_year.value = mtgecalc.prepaystrt.year;
}
	
function MortgagePutMtgeInfo(type)
{
	var tmpstr = "";
	
	if (type == 'mtgform')
	{
		tmpstr = '<FORM>'
			+ '<TR>'
			+	'<TD ALIGN="center" COLSPAN="2">'
			+	  '<INPUT TYPE="button" VALUE="Recalculate" onClick="ShowForm()">'
		+	  '<INPUT TYPE="button" VALUE="PrintResults" onClick="PrintResult()">'
			+	'</TD>'
			+ '</TR>'
			+ '</FORM>';
	}
	
	if (type == 'print')
	{
		tmpstr = '<TR>'
			+	'<TD ALIGN="left" COLSPAN="2" class="bg4">'
			+	  '<span class="hlite">Calculator Results</span>'
			+	'</TD>'
			+ '</TR>';
	}
	
	return ('<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="3" width="185" class="bg5">'
			+ tmpstr
			+ '<TR>'
			+ 	'<TD ALIGN="left" VALIGN="top">'
			+	  '<b>Proceeds :</b>'
			+	'<br>&euro;'
			+	  toCurrency(this.proceeds)
			+	'</TD>'
			+ '</TR>'
			+ '<TR>'
			+	'<TD ALIGN="left" VALIGN="top">'
			+	  '<b>Monthly Payment :</b>'
			+	'<br>&euro;'
			+	  toCurrency(this.mnthlypayment)
			+       '</TD>'
			+ '</TR>'
			+ '<TR>'
			+   	'<TD ALIGN="left" VALIGN="top">'
			+	  '<b>Effective Rate :</b>'
			+	  this.eff_rate  + '%'
			+	'</TD>'
			+ '</TR>'
		    +'</TABLE>');
}


function ShowResult()
{
PopulateForm(document.mortgage);
var body1 = mtgecalc.putMtgeInfo('print');
var body2 = mtgecalc.showAmortization();
if ((body1 != "") && (body2 != "")){
var tail = '<br><br>';
var all_results = '<table width="100%" border="0"><tr><td valign="top"><td valign="top" width="215">' 
				+ body1 + '</td><td valign="top" align="left">' + body2 + '</td></tr></table>';

	if ((navigator.appName.indexOf("Netscape") != -1)&& (parseInt(navigator.appVersion) == 4)) {
			var reslayer = document.layers['mtgeres2'].document;
			reslayer.open();
			reslayer.write(all_results);
			reslayer.close();
     } 
	 else if ((navigator.appName.indexOf("Microsoft") != -1) || 
	 		  (parseInt(navigator.appVersion) >= 5)){
			document.getElementById("mtgeres").innerHTML = all_results;
    } 
	else {
		alert("This calculator can only be used in a browser that supports web standards");
	}
}
else{
	return false;
}
}
