function YearIterator(month, year)
{
	this.month = month;
	this.year = year;
	
	this.monthArr = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
	

	
	this.next = function()
	{
		if(this.month == 12) {
			this.month = 1;
			this.year++;
		} else {
			this.month++;
		}
	}
	
	this.get = function()
	{
		var obj = new Object;
		obj.month = this.monthArr[(this.month-1)];
		obj.year = this.year;
		return obj;
	}
	
	this.toString = function()
	{
		obj = this.get();
		return obj.month + " " + obj.year;
	}
	
	this.yearChange = function()
	{
		if(this.month == 12) {
			return true;
		} else {
			return false;
		}
	}
	
}

function Mortgage() 
{
	this.principal = null;
	this.downPayment = null;
	this.interest = null;
	this.term = null;
	this.tax = null;
	this.pmi = null;
	this.insurance = null;
	
	this.modifier = 12;
	
	this.formHasErrors = false;
	
	this.dataGrid;
	
	this.tableContent;
	
	this.summary;
	
	this._monthlyPayment;
	
	this.usesPmi;
	
	this.graphData;
	
	this.getMonthlyPayment = function()
	{
		return this._monthlyPayment;
	}
	
	this.calculateMonthlyPayment = function()
	{
		var principal = this.principal;
		var downPayment = this.downPayment;
		var cInterest = this.interest/100/12;
		var payments  = this.term*12;

		var computed1 = Math.pow((1+cInterest), payments);
		var monthlyPayment = (principal-downPayment) * computed1 * cInterest / (computed1 - 1);
		
		this._monthlyPayment = parseFloat(monthlyPayment.toFixed(2));
	}
	
	this.getTax = function()
	{
		return parseFloat((this.tax/(this.modifier*100)*this.principal).toFixed(2));
	}
	
	this.getInsurance = function()
	{
		return parseFloat((this.insurance/(this.modifier*100)*this.principal).toFixed(2));
	}
	
	this.inputIsValid = function()
	{
		var flag = null;
		this.formHasErrors = false;
		
		this.principal = this.formatNumber("#principal", 2);
		flag = isNaN(this.principal) || this.principal<0 || this.principal>10000000
		this.toggleErrorFlag("#principal", flag);

		this.downPayment = this.formatNumber("#downPayment", 2);
		flag = isNaN(this.downPayment) || this.downPayment<0 || this.downPayment>this.principal;
		this.toggleErrorFlag("#downPayment", flag);
		
		this.interest = this.formatNumber("#interestRate", 2);
		flag = isNaN(this.interest) || this.interest<0 || this.interest>100;
		this.toggleErrorFlag("#interestRate", flag);
		
		this.term = this.formatNumber("#term", 2);
		flag = isNaN(this.term) || this.term<0 || this.term>100;
		//this.toggleErrorFlag("#term", flag);
		
		this.tax = this.formatNumber("#taxes", 2);
		flag = isNaN(this.tax) || this.tax<0 || this.tax>100;
		this.toggleErrorFlag("#taxes", flag);
		
		this.insurance = this.formatNumber("#insurance", 2);
		flag = isNaN(this.insurance) || this.insurance<0 || this.insurance>100;
		this.toggleErrorFlag("#insurance", flag);
		
		this.pmi = this.formatNumber("#pmi", 2);
		flag = isNaN(this.pmi) || this.pmi<0 || this.pmi>1000;
		this.toggleErrorFlag("#pmi", flag);

		
		return !this.formHasErrors;
	}
	
	this.formatNumber = function(input, decimal)
	{
		if(!$(input).attr("value")) {
			return 0.00;
		}
		var text = $(input).attr("value").replace(" ", "").replace(",", "");
		var num = new Number(text);

		if(isNaN(num)) {
			return num;
		}
		num = parseFloat(num.toFixed(decimal));
		return num;
	}
	
	this.toggleErrorFlag = function(input, flag) 
	{
		if(flag) {
			$(input).css({backgroundColor: "#FF0000", opacity:1});
			this.formHasErrors = true;
	    } else {
			$(input).css({backgroundColor: "#FFFFFF", opacity:1});
			return true;
		}
	}
	
	this.calculate = function()
	{
		this.calculateMonthlyPayment();
		
		var arr = new Array();

		var modifier = this.modifier;
		
		this.summary = new Object;

		var principal = parseFloat(this.principal);
		var downPayment = parseFloat(this.downPayment);
		var interest = this.interest/100;
		var payments  = this.term*modifier;
		
		var tax = this.getTax();
		var insurance  = this.getInsurance();
		var pmi  = this.pmi;

		var taxes = (tax+insurance);

		var balance = principal - downPayment;
		var mPayment = this.getMonthlyPayment();
		
		var owned = 0;
		
		var month = $("#date_month").attr("value");
		var year = $("#date_year").attr("value");
		var iterator = new YearIterator(month, year);
		
		this.summary.pmi = pmi;
		this.summary.totalInterest = 0;
		this.summary.total = 0;
		this.summary.totalTax = 0;
		this.summary.totalInsurance = 0;
		this.summary.totalPmi = 0;
		this.summary.pmiPaymentsNum = 0;
		
		this.graphData = new Object;
		this.graphData.balance = [];
		this.graphData.total = [];
		this.graphData.principal = [];
		this.graphData.interest = [];
		
		gdBalanceHelper = balance;
		gdTotalHelper = 0;
		gdPrincipalHelper = 0;
		gdInterestHelper = 0;
		
		var html = "<table id=\"data_table\">";
		html += "<thead>";
		html += "<tr><th>Date</th><th>Principal</th><th>Interest</th><th>Taxes</th><th>Balance</th></tr>";
		html += "</thead><tbody>";
		for(var i=0; i<this.term*modifier; i++) {
			var obj = new Object;
			obj.date = iterator.toString();
			obj.balance = parseFloat(balance);
			obj.interest = parseFloat((balance*interest/modifier).toFixed(2));
			
			obj.principal = parseFloat((mPayment-obj.interest).toFixed(2));
			if(balance - obj.principal < 0) {
				obj.principal += balance - obj.principal;
			}


			obj.pmi = 0;

			if((owned+downPayment)/principal < 0.2) {
				obj.pmi = parseFloat(pmi);
			} 
			obj.taxes = parseFloat(taxes)+obj.pmi;
			
			owned += obj.principal;
			
			obj.total = parseFloat((mPayment+parseFloat(taxes.toFixed(2))).toFixed(2)+obj.interest);

			this.summary.totalInterest += parseFloat(obj.interest.toFixed(2));
			this.summary.payOffDate = obj.date;
			this.summary.totalTax += tax;
			this.summary.totalInsurance += insurance;
			this.summary.totalPmi += parseFloat(obj.pmi.toFixed(2));
			
			if(obj.pmi > 0) {
				this.summary.pmiPaymentsNum++;
			}
			
			balance -= obj.principal;
			balance = parseFloat(balance.toFixed(2));
			obj.balance = balance;

			html += "<tr>";
			html += "<td>"+obj.date+"</td>";
			html += "<td>"+moneyFormat(obj.principal)+"</td>";
			html += "<td>"+moneyFormat(obj.interest)+"</td>";
			html += "<td>"+moneyFormat(obj.taxes)+"</td>";
			html += "<td>"+moneyFormat(obj.balance)+"</td>";
			html += "</tr>";

			gdBalanceHelper -= obj.principal;
			gdTotalHelper += obj.total;
			gdPrincipalHelper += obj.principal;
			gdInterestHelper += obj.interest;

			if(iterator.yearChange() || i==this.term*modifier-1) {
				this.graphData.balance.push([iterator.year, gdBalanceHelper]);
				this.graphData.total.push([iterator.year, gdTotalHelper]);
				this.graphData.principal.push([iterator.year, gdPrincipalHelper]);
				this.graphData.interest.push([iterator.year, gdInterestHelper]);
				
			} 

			arr[arr.length] = obj;
			iterator.next();
		} 

		this.summary.paymentsNum = arr.length;
		
		this.dataGrid = arr;
		this.tableContent = html+"</tbody></table>";
		html = null;
		arr = null;
	}
	
	this.buildSummary = function()
	{
		$(".txtSumPrincipal").text(moneyFormat(this.getMonthlyPayment()));
		$(".txtSumTax").text(moneyFormat(this.getTax()));
		$(".txtSumInsurance").text(moneyFormat(this.getInsurance()));
		$(".txtSumPmi").text(moneyFormat(this.pmi));
		
		var total = this.getMonthlyPayment()+this.getTax()+this.getInsurance();
		
		$("#txtPayOffDate").text(this.summary.payOffDate);
		$("#txtMonthlyPmi").text(moneyFormat(this.summary.pmi));
		
		var total = this.principal + this.summary.totalInterest;
		total += this.summary.totalPmi + this.summary.totalTax
		total += this.summary.totalInsurance;
		
		var pmiPayOff = "N/A";
		if(this.summary.pmiPaymentsNum>0) {
			pmiPayOff = this.dataGrid[this.summary.pmiPaymentsNum].date;
			$(".usesPMI").css("display", "inline");
		} else {
			$(".usesPMI").css("display", "none");
		}
		
		if(this.usesPmi) {
			this.pmiOn();
		} else {
			this.pmiOff();
		}
		
		$("#txtTotalPrincipal").text(moneyFormat(this.principal));
		$("#txtTotalPayment").text(moneyFormat(total));
		$("#txtTotalInterest").text(moneyFormat(this.summary.totalInterest));
		$("#txtTotalPmi").text(moneyFormat(this.summary.totalPmi));
		$("#txtTotalTax").text(moneyFormat(this.summary.totalTax));
		$("#txtTotalInsurance").text(moneyFormat(this.summary.totalInsurance));
		$("#txtPmiNumber").text(this.summary.pmiPaymentsNum);
		$("#txtNumberOfPayments").text(this.dataGrid.length);
		$(".txtPmiPayOffDate").text(pmiPayOff);
		
		$(".highlight")
			.animate({ backgroundColor: "#FDD017" }, 250)
			.animate({ backgroundColor: "#FFFFFF" }, 500, null, function() {
				$(this).css("backgroundColor", "#FFFFFF");
			});	
	}
	
	this.buildTable = function()
	{
		this.buildTableAsync();return;
		setTimeout(this.buildTableAsync(), 0);
	}
	
	this.buildTableAsync = function()
	{
		document.getElementById('amortizationBody').innerHTML=this.tableContent;
	}
	
	this.buildChart = function()
	{

		var dataSet = {
			"balance": { 
				"data": this.graphData.balance,
				"label": "Balance"
			},
			"principal": {
				"data": this.graphData.principal,
				"label": "Principal"
			},
			"interest": {
				"data": this.graphData.interest,
				"label": "Interest"
			},
			"total": {
				"data": this.graphData.total,
				"label": "Total"
			}
		}
		var i = 0;
		$.each(dataSet, function(key, val) {
			val.color = i;
			++i;
		});

		var data = [];
		
		$(".plotChoice:checked").each(function(i) {
			data.push(dataSet[$(this).attr("name")]);
		});
		
		$("#placeholder").css("display", "block");
		$.plot($("#placeholder"), 
			data,
			{ 
				lines: { show: true },
            	points: { show: true },
             	selection: { mode: "xy" },
             	grid: { hoverable: true, clickable: true }
            }
		);

    	var previousPoint = null;
    	$("#placeholder").bind("plothover", function (event, pos, item) {

            if (item) {
                if (previousPoint != item.datapoint) {
                    previousPoint = item.datapoint;
                    
                    $("#tooltip").remove();
                    var x = item.datapoint[0].toFixed(2),
                        y = item.datapoint[1].toFixed(2);
                    
                    showTooltip(item.pageX, item.pageY,
                                item.series.label + ", " + parseInt(x) + ", $" + y);
                }
            }
            else {
                $("#tooltip").remove();
                previousPoint = null;            
            }
        
    	});
		

	}
	
	this.buildRepaymentChart = function() 
	{
		
		var total = this.principal + this.summary.totalInterest;
		total += this.summary.totalPmi + this.summary.totalTax
		total += this.summary.totalInsurance;
		
		var d2 = [
			[1, this.principal/total], 
			[3, this.summary.totalInterest/total], 
			[5, this.summary.totalInsurance/total], 
			[7, this.summary.totalTax/total],
			[9, this.summary.totalPmi/total]
		];

		var yaxis = [];
		for(var i=0; i<=1; i+=0.1) {
			yaxis.push([i, parseInt(i*100)+"%"]);
		}

		$.plot($("#placeholder2"), 
		[ { data: d2, bars: { show: true } } ],
		{
			xaxis: {
			 	ticks: [
				 	[0, 0], 
					[1.5, "Principal"], 
					[3.5, "Interest"], 
					[5.5, "Property Insurance"], 
					[7.5, "Property Tax"], 
					[9.5, "PMI"]
				],
				min: 0.50,
				max: 10.5
        	},
			yaxis: {
				ticks: yaxis
			}

		});

	}
	
	this.loop = function(tab)
	{
		if(!this.inputIsValid()) {
			return null;
		}
		
		tab = this.getActiveTab(tab);
		this.calculate();

		if(tab == "#tab2") {
			this.buildTable();
		} else if(tab == "#tab3") {
			this.buildChart();
		} else if(tab == "#tab4") {
			this.buildRepaymentChart();
		} else {
			this.buildSummary();
		}	
	}
	
	this.getActiveTab = function(sTab) 
	{
		if(sTab != undefined) {
			return sTab;
		}
		
		var arr = new Array("#tab1", "#tab2", "#tab3", "#tab4");
		
		for(i in arr) { 

			if($(arr[i]).css("display") == "block") {
				return arr[i];
			}
		}
	}

	this.pmiOn = function() 
	{
		this.usesPmi = true;
		$("#pmiOn").css("text-decoration", "underline");
		$("#pmiOff").css("text-decoration", "none");
		
		var pmi = 0;
		var tPmi = "0.00";
		if(this.summary.pmiPaymentsNum>0) {
			pmi = this.pmi;
			tPmi = this.summary.pmi;
		}

		$(".txtSumPmi").text(moneyFormat(parseFloat(tPmi)));
		var mPayment = this.getMonthlyPayment()+this.getTax()+this.getInsurance()+pmi;
		$("#txtSumTotalAlt").text(moneyFormat(mPayment));
		return false;
	}
	
	this.pmiOff = function() 
	{
		this.usesPmi = false;
		$("#pmiOn").css("text-decoration", "none");
		$("#pmiOff").css("text-decoration", "underline");
		
		$(".txtSumPmi").text("0.00");
		var mPayment = this.getMonthlyPayment()+this.getTax()+this.getInsurance();
		$("#txtSumTotalAlt").text(moneyFormat(mPayment));
		return false;
	}

}


$(function() {

	var mortgage = new Mortgage;
	
	$("input.event").bind("keyup", function() {
		mortgage.loop();	
	});
	
	$("select.event").bind("change", function() {
		mortgage.loop();	
	});
	
	$("#pmiOn").bind("click", function() {
		mortgage.pmiOn();
		return false;
	}, false);
	
	$("#pmiOff").bind("click", function() {
		mortgage.pmiOff();
		return false;
	}, false);
	
	$('#tabPane').tabs({
		onShow: function(e) {
			mortgage.loop(e.hash);	
		}
	});
	
	$(".plotChoice").bind("click", function() {
		mortgage.buildChart();
	});
	
	mortgage.loop();
	mortgage.pmiOn();
	
});

function showTooltip(x, y, contents) {
    $('<div id="tooltip">' + contents + '</div>').css( {
        position: 'absolute',
        display: 'none',
        top: y + 5,
        left: x + 5,
        border: '1px solid #fdd',
        padding: '2px',
        'background-color': '#fee',
        opacity: 0.80
    }).appendTo("body").fadeIn(200);
}

function moneyFormat(x)
	{
		var split = x.toFixed(2).toString().split(".");
		var x1 = split[0];
		
		var diff = x1.length%3;
		var mod = 1;
		var iterations = (x1.length-diff)/3;
		
		if(diff == 0) {
			diff = 3;
			mod = 0;
		}
		
		iterations += mod;
		var arr = new Array();
		
		for(var i=0; i<iterations; i++) {
			arr[arr.length] = x1.substr(0, diff);
			x1 = x1.substr(diff);
			diff = 3;
		}
		arr = arr.join(",") + "." + split[1];
		
		return arr;
	}
	

