﻿jQuery(function ($) {

	/*
	  * 
	  * multi-line graph generator for Advocate Capital Real Costs calculator
	  *
	*/

	// Run the code when the DOM is ready
	$(calcRealCosts);
	$(calcCosts);

	//some globals for arrays and various canvas functions
	var selfFunding = [];
	var otherLender = [];
	var aciPassThrough = [];
	var can, ctx, maxVal, minVal, xScalar, yScalar, numYears;
	var colHead = 50;
	var rowHead = 90;
	var margin = 30;

	//recaclc onclick
	function calcRealCosts() {
		$("#recalculate").click(function () {
			calcCosts();
		});
	} //end recalc

	//main calc code with defaults for initial graph and data table genreation
	function calcCosts() {
		//form field values
		var funds = "1000000";
		if ($("#funds").val()) {
			funds = $("#funds").val();
		}
		var funds = funds.replace(/[^\d.]/g, "");

		//error check - this calculator is much more flexible
		//than the original built in flash, so the min & max
		//values for form fields can be changed as needed
		funds = formErr("fundErr", "funds", "case expenses are ", funds, 5000000, 50000, "");

		//dynamic tax rate
		var preTaxRate = 8; // formerly "10%"
		if ($("#pretaxRate").val()) {
			preTaxRate = $("#pretaxRate").val();
		}
		var preTaxRate2 = preTaxRate.replace(/[^\d.]/g, "");

		//error check
		preTaxRate2 = formErr("ptrateErr", "pretaxRate", "investment rate is ", preTaxRate2, 25, 3, "%");

		//dynamic annual rate
		var annualRate = 5.5; //6.5 //5;   ////4.25; //formerly "4.25%"

		if ($("#annualRate").val()) {

			annualRate = $("#annualRate").val();

		}
		//alert(annualRate);
		//var annualRate2 = annualRate.replace(/[^\d.]/g, "");
		var annualRate2 = annualRate;
		//alert(annualrate2);
		//error check and format correction of funds field
		annualRate2 = formErr("arateErr", "annualRate", "interest rate is ", annualRate2, 30, 3, "%");

		numYears = 25; //fixed value for this exercise
		var inflation = .03; //027; //.03; //fixed value for this exercise
		var incomeTaxRate = .35; //36  //fixed value for this exercise
		var casefundsRecoup = .95; //fixed value for this exercise
		/////var aciFee = .1545; //fixed value for this exercise
		var aciFee = .177;//.162 //.1595; //fixed value for this exercise


		//Getting information from page, that was load from Umbraco
		if ($("#inflation").text()) {
			inflation = $("#inflation").text();
		}

		if ($("#incomeTaxRate").text()) {
			incomeTaxRate = $("#incomeTaxRate").text();
		}
		if ($("#casefundsRecoup").text()) {
			casefundsRecoup = $("#casefundsRecoup").text();
		}
		if ($("#aciFee").text()) {
			aciFee = $("#aciFee").text();
		}

		//present-value multipliers
		var bviDiffCostAT = ((parseFloat(annualRate2) / 100) * (1 - incomeTaxRate)) - ((parseFloat(preTaxRate2) / 100) * (1 - incomeTaxRate));
		var aciviDiffCostAT = ((aciFee * (1 - casefundsRecoup)) * (1 - incomeTaxRate)) - ((parseFloat(preTaxRate2) / 100) * (1 - incomeTaxRate));
	
		//calculate the self-funding, other-lender, and ACI values over 25 years based on form data and fixed values, above
		var fundsTemp = parseFloat(funds);

		var otherLenderBal = [];
		var lenderBalTemp = parseFloat(funds);
		var lenderValTemp;

		var aciPassThroughBal = [];
		var aciBalTemp = parseFloat(funds);
		var aciValTemp;

		for (var i = 0; i < 25; i++) {//25 year array of value based on investment criteria
			fundsTemp = parseFloat(fundsTemp) * (1 - inflation);
			selfFunding[i] = Math.round(fundsTemp);

			//lenderBalTemp = Math.round(lenderBalTemp * (1-bviDiffCostAT));
			lenderBalTemp = lenderBalTemp * (1 - bviDiffCostAT);
			lenderBalTemp = precision_round(lenderBalTemp, 2);
			lenderValTemp = lenderBalTemp * Math.pow((1 - inflation), i + 1);
			lenderValTemp = precision_round(lenderValTemp, 2);
			otherLender[i] = lenderValTemp;

			aciBalTemp = aciBalTemp * (1 - aciviDiffCostAT);
			aciBalTemp = precision_round(aciBalTemp, 2);
			aciValTemp = aciBalTemp * Math.pow((1 - inflation), i + 1);
			aciValTemp = precision_round(aciValTemp, 2);
			aciPassThrough[i] = aciValTemp;
		} //end for

		//set ratios based on the canvas height to allow for any fund and rate values
		can = document.getElementById("can");
		can.width = can.width; //clear the canvas so that recalcs are clean

		ctx = can.getContext("2d");

		maxVal = getMaxY();
		maxValLabel = Math.round(maxVal);  //labels need full value
		minValLabel = Math.round(minVal);  //labels need full value
		yRatio = maxVal / (can.height - colHead - margin);
		maxVal = maxVal / yRatio;

		minVal = getMinY();
		minVal = minVal / yRatio;

		var stepSize = (can.height - colHead - margin) / 60;

		//base font color and size - needs to be reset after each change
		ctx.fillStyle = "#000"
		ctx.font = "10pt Verdana"

		// set vertical scalar to available height / data points

		////yScalar = (can.height - colHead - margin) / (maxVal - minVal);
		yScalar = (can.height + margin) / (maxVal - minVal);

		// set horizontal scalar to available width / number of samples

		xScalar = (can.width - rowHead) / numYears;

		ctx.beginPath(); //needed often, as we are drawing a large number of different paths on the same canvas

		//title for graph
		ctx.textAlign = 'center';
		ctx.fillStyle = "#024930";
		ctx.font = "12pt Verdana";
		ctx.fillText("Save Money with Advocate Capital!", (can.width + rowHead) / 2, colHead - margin);
		ctx.textAlign = 'left';//reset left-align

		//outline created using a black rectangle 1px larger in all dimensions behind a fill
		//less code that multiple line draws
		ctx.fillStyle = "#000";
		ctx.font = "12pt Verdana";
		ctx.fillRect(rowHead - 1, margin - 1, can.width, (can.height - colHead - 8));

		//gradient fill
		var lingrad = ctx.createLinearGradient(0, 0, 0, can.height * .9);
		lingrad.addColorStop(0.1, '#e1e1e1');
		lingrad.addColorStop(1, '#e1e1e1');
		ctx.fillStyle = lingrad;
		ctx.fillRect(rowHead, margin, can.width - (rowHead + 1), (can.height - colHead - 10));
		ctx.fillStyle = "#000";

		//array of years
		var header = [];
		header[0] = " ";
		for (i = 1; i < numYears + 1; i++) {
			header[i] = i;
		}

		// print years
		ctx.strokeStyle = "#969996"; // grey grid lines
		////for (i = 1; i <= numYears+1; i++) {
		for (i = 1; i <= numYears + 1; i = i + 2) {
			var headX = i * xScalar; //adjust the position of the header values
			var lineX = i * xScalar;

			ctx.moveTo(lineX, colHead);

			//year labels
			if (header[i]) {
				ctx.font = "10pt Verdana";
				ctx.fillText(header[i], (headX + rowHead - 10), can.height - (margin / 2));
			}

			ctx.fillText("YEARS", can.width / 2, can.height);
		} //end for

		// print row header and draw horizontal grid lines
		var count = 0;

		for (scale = maxValLabel; scale >= minValLabel; scale -= stepSize * yRatio) {

			var y = colHead + (yScalar * count * stepSize);

			ctx.moveTo(rowHead, y);

			if (count % 5 == 0) {
				ctx.lineTo(can.width, y);
				ctx.font = "10pt Verdana";

				ctx.fillText(dollarFormat(scale, 1), 0, y);

			}

			count++;
		} //end for

		ctx.stroke();

		// set a color and make one call to plot data for each data set

        ctx.strokeStyle = "#ffcc00";
        ctx.fillStyle = "#ffcc00";
		plotDataLines(selfFunding);
		plotDataPoints(selfFunding);

		ctx.strokeStyle = "#990000";
		ctx.fillStyle = "#990000";
		plotDataLines(otherLender);
		plotDataPoints(otherLender);

        ctx.strokeStyle = "#009933";
        ctx.fillStyle = "#009933";
		plotDataLines(aciPassThrough);
		plotDataPoints(aciPassThrough);

		//draw the chart key
		chartKey();
		chartData();

	}//end calcCosts

	// Returns the max Y value in our data list
	function getMaxY() {
		var maxTemp = 0;

		for (var i = 0; i < numYears; i++) {
			if (selfFunding[i] > maxTemp) {
				maxTemp = selfFunding[i];
			}

			if (otherLender[i] > maxTemp) {
				maxTemp = otherLender[i];
			}

			if (aciPassThrough[i] > maxTemp) {
				maxTemp = aciPassThrough[i];
			}
		}

		return maxTemp;
	}// end getMaxY

	// Returns the min Y value in our data list
	function getMinY() {
		var minTemp = 0;

		for (var i = 0; i < numYears; i++) {
			if (selfFunding[i] < minTemp) {
				minTemp = selfFunding[i];
			}

			if (otherLender[i] < minTemp) {
				minTemp = otherLender[i];
			}

			if (aciPassThrough[i] < minTemp) {
				minTemp = aciPassThrough[i];
			}
		}
		return minTemp;

	}//end getMinY

	//multiple fnuctions for lines, dots, and key to make it easier to deal with the multiple calls to canvas functions
	function plotDataLines(investData) {

		ctx.beginPath();
		//start at first data point
		ctx.moveTo((1 * xScalar + rowHead - 10), ((can.height - margin) - (Math.round(investData[0] / yRatio))));


		for (i = 0; i < numYears; i++) {
			//draw the line to the next data point
			ctx.lineTo(((i + 1) * xScalar + rowHead - 10), ((can.height - margin) - (Math.round(investData[i] / yRatio))));
		}

		ctx.stroke();
	}//end plotDataLines

	//multiple beginPath statements, because we don't want to stretch the dots between data points
	function plotDataPoints(investData) {
		//start at first data point
		ctx.moveTo((1 * xScalar + rowHead - 10), ((can.height - margin) - (Math.round(investData[0] / yRatio))));

		//Draw the dots
		for (i = 0; i < numYears; i++) {
			//draw the dot at the next data point
			ctx.beginPath();
			ctx.arc(((i + 1) * xScalar + rowHead - 10), ((can.height - margin) - (Math.round(investData[i] / yRatio))), 4, 0, Math.PI * 2, true);
			ctx.fill();
		}

	}//end plotDataPoints

	//money should look like money
	//updated 2012_12_06 to conditionally show the dollar sign, 
	//to allow for updates of the form field
	function dollarFormat(x, showSign) {
		var dollars = Math.round(x);
		dollars = dollars.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		if (showSign == 1) {
			dollars = "$" + dollars;
		}
		return dollars;
	}//end dollarFormat

	//key with matching color values
	function chartKey() {
		//outline created using a black rectangle 1px larger in all dimensions behind a fill
		//less code that multiple line draws
		ctx.fillStyle = "#000";
		//  ctx.fillRect (4*xScalar-1, (1.5*margin-1), (6*xScalar+2), (1.5*margin+2));
		ctx.fillRect(4 * xScalar - 1, (1.5 * margin - 1), (8 * xScalar + 2), (1.5 * margin + 2));

		//fill
		ctx.fillStyle = "#fff";
		ctx.fillRect(4 * xScalar, (1.5 * margin), (8 * xScalar), (1.5 * margin));

		//text
		ctx.fillStyle = "#333";
		ctx.font = "8pt Verdana";
		ctx.fillText("Advocate Capital, Inc.", (4 * xScalar + 30), (2 * margin - 2));
		ctx.fillText("Self-Funding", (4 * xScalar + 30), (2 * margin + 10));
		ctx.fillText("Other Lender", (4 * xScalar + 30), (2 * margin + 22));

		//color lines
		ctx.beginPath();
        ctx.strokeStyle = "#009933";
		ctx.moveTo((4 * xScalar + 10), (2 * margin - 6));
		ctx.lineTo((4 * xScalar + 25), (2 * margin - 6));
		ctx.stroke();
		ctx.beginPath();
        ctx.strokeStyle = "#ffcc00";
		ctx.moveTo((4 * xScalar + 10), (2 * margin + 6));
		ctx.lineTo((4 * xScalar + 25), (2 * margin + 6));
		ctx.stroke();
		ctx.beginPath();
        ctx.strokeStyle = "#990000";
		ctx.moveTo((4 * xScalar + 10), (2 * margin + 18));
		ctx.lineTo((4 * xScalar + 25), (2 * margin + 18));
		ctx.stroke();
	}//end chartKey

	//table of data to go with the graph
	function chartData(self, other, aci) {
		cD = document.getElementById("chartData");
		var endofYear;
		var dataTable = '<table><tbody>';
		//	dataTable += '<tr><th colspan="4">Future Value of Your Money</th></tr>';
		dataTable += '<tr>';
		//	dataTable += "<td></td>";
		//	dataTable += "<td></td>";
		dataTable += '<td colspan="4" align="center"><strong>Borrow and Invest</strong></td>';
		dataTable += '</tr>';
		dataTable += '<tr>';
		dataTable += '<td>End of Year</td>';
		dataTable += '<td>Self-Funding</td>';
		dataTable += '<td>Other Lender</td>';
		dataTable += '<td>Advocate Capital, Inc.</td>';
		dataTable += '</tr>';
		dataTable += '<tr><td colspan="4" style="font-size: 0; border-bottom: 1px solid #333;">&nbsp;</td></tr>';
		for (var i = 0; i < numYears; i++) {
			endofYear = i + 1;
			dataTable += '<tr>';
			dataTable += '<td>' + endofYear + '</td>';
			dataTable += '<td>' + dollarFormat(selfFunding[i], 1) + '</td>';
			//document.write("<td>"+otherLenderBal[i]+"</td>");
			dataTable += '<td>' + dollarFormat(otherLender[i], 1) + '</td>';
			//document.write("<td>"+aciPassThroughBal[i]+"</td>");
			dataTable += '<td>' + dollarFormat(aciPassThrough[i], 1) + '</td>';
			dataTable += '</tr>';
			if (endofYear < numYears && endofYear % 5 == 0) {
				dataTable += '<tr><td colspan="4"  style="font-size: 0; border-bottom: 1px solid #333;">&nbsp;</td></tr>';
			}
		} //end for
		dataTable += '</tbody></table>';
		cD.innerHTML = dataTable;
	}

	//set limits - less necessary than with the legacy calculator
	//modified 2013_07_28 to use precision_round function to improve rounding based on value type
	function formErr(divName, fieldName, fieldLabel, curVal, maxVal, minVal, valType) {
		dID = document.getElementById(divName);
		fID = document.getElementById(fieldName);
		//return value so that other functions that rely 
		//on the variables set from fieldName values have 
		//current values, instead of original values
		var retVal = curVal;
		var errmsg;

		if (curVal > maxVal) {
			errmsg = "Maximum " + fieldLabel + maxVal + valType;
			if (valType != "%") {
				fID.value = dollarFormat(maxVal, 0);
			} else {
				fID.value = precision_round(maxVal, 2);
			}
			retVal = maxVal;
		} else if (curVal < minVal) {
			errmsg = "Minimum " + fieldLabel + minVal + valType;
			if (valType != "%") {
				fID.value = dollarFormat(minVal, 0);
			} else {
				fID.value = precision_round(minVal, 2);
			}
			retVal = minVal;
		} else { //always set the form field to the correct format
			if (valType != "%") {
				fID.value = dollarFormat(curVal, 0);
			} else {
				fID.value = precision_round(curVal, 2);
			}
		}
		if (errmsg) {
			dID.innerHTML = errmsg;
		} else {
			dID.innerHTML = "";
		}
		return retVal;
	}

	//improve rounding of form field entries
	//added 2013_07_28
	function precision_round(numval, decplaces) {
		return Math.round(numval * Math.pow(10, decplaces)) / Math.pow(10, decplaces);
	}
});