/*
 * CashulatorJS
 * 
 * 
*/

//HELP SECTION//
var help_alerts = new Array();

help_alerts['Loan Amount'] = '<div class="cashulator_doc_title">Loan Amount Tip</div><p>Enter the amount of money you would like to borrow.  Round the number to the nearest dollar, and do not include any punctuation or other types of characters.  For example, enter $10,000.32 as 10000.</p>';
help_alerts['Interest Rate'] = '<div class="cashulator_doc_title">Interest Rate Tip</div><p>Enter the interest rate at which you would like to borrow money.  The interest rate you enter can include up to two decimal places.  For example, if you\'d like to calculate your monthly payment for an interest rate of 7.95%, enter 7.95.</p>';
help_alerts['Years'] = '<div class="cashulator_doc_title">Years Tip</div><p>Enter the number of years for which you would like to borrow money.  (The more years over which your loan extends, the lower your payment will be, but the more interest you will pay.)</p>';
help_alerts['Payment Frequency'] = '<div class="cashulator_doc_title">Payment Frequency Tip</div><p>Select how often you would like to make loan payments. <br /><br />Monthly = Once a month (12 payments per year)<br /><br />Semi-monthly = Twice a month (24 payments per year)<br /><br />Weekly = Once a week (52 payments per year)</p>';

help_alerts['Mortgage Amount'] = '<div class="cashulator_title">Loan Amount Tip</div><p>Enter the amount of money you would like to borrow to purchase/refinance your home; do not include in this number any down payment you will be making.  For example, if your total home cost is $100,000 and you will be making a down payment of $20,000, enter 80000.</p>';
help_alerts['Mortgage Interest Rate'] = '<div class="cashulator_doc_title">Interest Rate Tip</div><p>Enter the interest rate at which you would like to borrow money.  The interest rate you enter can include up to two decimal places.  For example, if you\'d like to calculate your monthly payment for an interest rate of 6.75%, enter 6.75.</p>';
help_alerts['Mortgage Years'] = '<div class="cashulator_title">Years Tip</div><p>Enter the number of years over which you will be financing your home.  (The more years over which your mortgage extends, the lower your payment will be, but the more interest you will pay.)</p>';
help_alerts['Mortgage Payment Frequency'] = '<div class="cashulator_title">Payment Frequency Tip</div><p>Select how often you would like to make mortgage payments.<br /><br />Monthly = Once a month (12 payments per year)<br /><br />Bi-weekly = Every other week (26 payments per year)<br /><br />Weekly = Once a week (52 payments per year)</p>';

help_alerts['Retirement Goal'] = '<div class="cashulator_title">Retirement Goal Tip</div><p>Enter the amount of money you would like to have saved by the time you retire.  Round the number to the nearest dollar, and do not include any punctuation or other types of characters.  For example, enter $200,000.32 as 200000.</p>';
help_alerts['Retirement Interest Rate'] = '<div class="cashulator_doc_title">Interest Rate Tip</div><p>Enter the interest rate that you anticipate your savings will earn.  The interest rate you enter can include up to two decimal places.  For example, if you\'d like to calculate your savings based on an interest rate of 4.23%, enter 4.23.</p>';
help_alerts['Rate of Inflation'] = '<div class="cashulator_doc_title">Rate of Inflation Tip</div><p>Your best estimation of what the rate of inflation will be during this period. Usually four or five percent is a realistic guess.</p>';
help_alerts['Age of Retirement'] = '<div class="cashulator_title">Age of Retirement Tip</div><p>Typically age of retirement is between 60 and 65.</p>';
help_alerts['Your Age'] = '<div class="cashulator_title">Your Age Tip</div><p>Enter the age at which you plan to start saving for retirement.</p>';

help_alerts['Payment Amount'] = '<div class="cashulator_doc_title">Payment Amount Tip</div><p>Enter the amount of money you can afford to save every period.  Round the number to the nearest dollar, and do not include any punctuation or other types of characters.  For example, enter $10,000.32 as 10000.</p>';
help_alerts['Savings Years'] = '<div class="cashulator_doc_title">Years Tip</div><p>Enter the number of years for which you would like to save money.</p>';
help_alerts['Savings Payment Frequency'] = '<div class="cashulator_title">Savings Frequency Tip</div><p>Select how often you would like to make savings deposits.<br /><br />Monthly = Once a month (12 deposits per year)<br /><br />Bi-weekly = Every other week (26 deposits per year)<br /><br />Weekly = Once a week (52 deposits per year)</p>';
help_alerts['Savings Amount'] = '<div class="cashulator_doc_title">Savings Amount Tip</div><p>Enter the amount of money you can afford to save every period.  Round the number to the nearest dollar, and do not include any punctuation or other types of characters.  For example, enter $100.32 as 100.</p>';

function cashulator_help(what){
	var win = window.open('about:blank','cash_help','width=400,height=250,scrollbar=auto');
	win.document.open();
	win.document.write('<html><head><title>Help : '+what+'</title><link rel="stylesheet" type="text/css" href="cashulator.css" /></head><body><div class="cashulator_doc">');
	win.document.write((help_alerts[what]?help_alerts[what]:'There\'s no information on that topic at this time.'));
	win.document.write('</div><div align="center"><form><input class="cashulator_input" type="button" value="close" onClick="window.close();"></form></div></body></html>');
	win.document.close();
   }


//currency function//
function currency(num) {
   num = num.toString().replace(/\$|\,/g,'');
   if(isNaN(num))
   num = "0";
   sign = (num == (num = Math.abs(num)));
   num = Math.floor(num*100+0.50000000001);
   cents = num%100;
   num = Math.floor(num/100).toString();
   if(cents<10)
   cents = "0" + cents;
   for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
   num = num.substring(0,num.length-(4*i+3))+','+
   num.substring(num.length-(4*i+3));
   return (((sign)?'':'-') + '$' + num + '.' + cents);
}

//sprintf function//
function sprintf()
		{
			if (!arguments || arguments.length < 1 || !RegExp)
			{
				return;
			}
			var str = arguments[0];
			var re = /([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X)(.*)/;
			var a = b = [], numSubstitutions = 0, numMatches = 0;
			while (a = re.exec(str))
			{
				var leftpart = a[1], pPad = a[2], pJustify = a[3], pMinLength = a[4];
				var pPrecision = a[5], pType = a[6], rightPart = a[7];
				
				//alert(a + '\n' + [a[0], leftpart, pPad, pJustify, pMinLength, pPrecision);

				numMatches++;
				if (pType == '%')
				{
					subst = '%';
				}
				else
				{
					numSubstitutions++;
					if (numSubstitutions >= arguments.length)
					{
						alert('Error! Not enough function arguments (' + (arguments.length - 1) + ', excluding the string)\nfor the number of substitution parameters in string (' + numSubstitutions + ' so far).');
					}
					var param = arguments[numSubstitutions];
					var pad = '';
					       if (pPad && pPad.substr(0,1) == "'") pad = leftpart.substr(1,1);
					  else if (pPad) pad = pPad;
					var justifyRight = true;
					       if (pJustify && pJustify === "-") justifyRight = false;
					var minLength = -1;
					       if (pMinLength) minLength = parseInt(pMinLength);
					var precision = -1;
					       if (pPrecision && pType == 'f') precision = parseInt(pPrecision.substring(1));
					var subst = param;
					       if (pType == 'b') subst = parseInt(param).toString(2);
					  else if (pType == 'c') subst = String.fromCharCode(parseInt(param));
					  else if (pType == 'd') subst = parseInt(param) ? parseInt(param) : 0;
					  else if (pType == 'u') subst = Math.abs(param);
					  else if (pType == 'f') subst = (precision > -1) ? Math.round(parseFloat(param) * Math.pow(10, precision)) / Math.pow(10, precision): parseFloat(param);
					  else if (pType == 'o') subst = parseInt(param).toString(8);
					  else if (pType == 's') subst = param;
					  else if (pType == 'x') subst = ('' + parseInt(param).toString(16)).toLowerCase();
					  else if (pType == 'X') subst = ('' + parseInt(param).toString(16)).toUpperCase();
				}
				str = leftpart + subst + rightPart;
			}
			return str;
		}
      
      
//CASHULATOR SECTION//
function CashulatorJS(name){

   this.name = name;
   this.o = new Array();
   this.i = new Array();
   this.fields = null;
  
   this.get_input_value = function(e){
      if(e.type!=null)
         switch(e.type){
            case "text": case "hidden": case "password": case "textarea": case "file":return(e.value);break;
            case "checkbox":return(((e.checked)?e.value:''));break;
            case "select-one":var o = e.options[e.selectedIndex];
               return(((o.value==null)?o.text:o.value));break;
            case "radio":return((e.checked)?e.value:null);break;
            }
      else //pesky radio button//
         for(var cnt=0;cnt<e.length;cnt++)
            if(e[cnt].checked)return(e[cnt].value);

      return(false);
   };


   this.set_input_value = function(element,value){
      if(element.type!=null)
         switch(element.type){
            case "text":case "hidden":case "password":case "textarea":element.value = value;break;
            case "checkbox":element.checked = (element.value == value);break;
            case "select-one": 
               for(var cnt=0;cnt<element.options.length;cnt++)
                  if(element.options[cnt].value == value || element.options[cnt].text == value){
                     element.selectedIndex = cnt;break;}
            }
      else		
         for(var cnt=0;cnt<element.length;cn++)
            if(element[cnt].value == value){
               element[cnt].checked = true;break;}
	};

   //perform the calculation and display the results//
   this.exec = function(e){

      this.fields = e.form.elements;
      var names = new Array();

      //get names//
      for (var cnt=0;cnt<this.fields.length;cnt++){
         if (this.fields[cnt].name){
            names[this.fields[cnt].name] = this.fields[cnt].name;
         }
      }

      //get values//
      for (name in names){
         this.i[name] = this.get_input_value(this.fields[name]);
      }

      //process//
      this.eval(this.i);

      //output//
      for (out in this.o){
         var n = document.getElementById('_CJS.out.' + out);
         if (n){
            n.innerHTML = this.o[out];
         }
      }

      //turn on results div//
      var n = document.getElementById('_CJS.out');
      n.style.display = 'block';
   }
   
}

/************************************************************************************/
// INDIVIDUAL CHARACTERS
/************************************************************************************/

var _CJS = new Array();

/******************************************************
 * Invest Goal
 */

_CJS['Invest Goal'] = new CashulatorJS('Invest Goal');
_CJS['Invest Goal'].eval = function(i){
   var Interest = i['Rate'] / 100; 
   var BegAmt = i['EndAmt'] / (Math.exp(i['Years']*Math.log(1+Interest)));

   //--- RESULTS API ASSIGNMENT ---//

   this.o['BegAmt']  = currency(BegAmt);
   this.o['Rate']    = sprintf("%01.2f", i['Rate']);
   this.o['EndAmt']  = currency(i['EndAmt']);
   this.o['EarnInt'] = currency(i['EndAmt']-BegAmt);
   this.o['Years']   = i['Years'];
}


/******************************************************
 * Loan Payment
 */

_CJS['Loan Payments'] = new CashulatorJS('Loan Payments');
_CJS['Loan Payments'].eval = function(i){
   var AmtToPay = i['LoanAmt'];
   var Interest = i['LoanRate']/(100*i['LoanPeriod']); //{i# = R / (100 * M) }
   var Periods = i['LoanYears'] * i['LoanPeriod']; //{N# = N# * M}
   var Temp = Math.exp(-Periods*Math.log(1+Interest));
   var PmtAmt = AmtToPay/((1-Temp)/Interest);
   var PaidAmt = PmtAmt * Periods; //{XX# = X# * N#}

   var data1 = new Array();
   var data2 = new Array();
   var total = AmtToPay;
   var interest = principle = 0;

   for(var cnt=1;cnt<=Periods;cnt++){
      int_change = ((total * Interest)<0)?0:(total * Interest);
      interest += int_change;
      principle += PmtAmt - int_change;

      if((cnt % i['LoanPeriod']) == 0 || cnt == Periods){
         data1[data1.length] = interest;
         data2[data2.length] = principle;
         interest = principle = 0;
         }

      total -= PmtAmt - int_change;
   }   

   //--- RESULTS API ASSIGNMENT ---//

   this.o['PmtAmt']  = currency(PmtAmt);
   this.o['LoanRate'] = sprintf("%01.2f", i['LoanRate']);
   this.o['LoanAmt'] = currency(i['LoanAmt']);
   this.o['IntPaid'] = currency(PaidAmt-AmtToPay);
   this.o['LoanYears']   = i['LoanYears'];
   this.o['LoanPeriod']  = i['LoanPeriod'];

   var graph = new Graphite();
   graph.title = "Loan Payments";
   graph.bar_padding = 0;
   graph.padding = 5;
   graph.y_width = 80;
   graph.x_label = 'Years';
   graph.y_label = 'Amount Paid';
   graph.add_list(data1,'Interest','');
   graph.add_list(data2,'Principal','');

   this.o['loan_payments_graph'] = graph.create();

}

/******************************************************
 * Loan Payment
 */

_CJS['Loan Comparison'] = new CashulatorJS('Loan Comparison');
_CJS['Loan Comparison'].eval = function(i){

   //loan1//
   Interest = i['RateComp']/(100*i['PeriodComp']); //{i# = R / (100 * M) }
   Periods = i['YearsComp'] * i['PeriodComp']; //{N# = N# * M}
   Temp = Math.exp(-Periods*Math.log(1+Interest));
   PmtAmt = i['LoanCompAmt']/((1-Temp)/Interest);
   PaidAmt = PmtAmt * Periods; //{XX# = X# * N#}

   Adata1 = new Array();
   Adata2 = new Array();
   total = i['LoanCompAmt'];
   principle = 0;
   interest = 0;

   for(cnt=1;cnt<=Periods;cnt++){
      int_change = (total * Interest)<0?0:(total * Interest);
      interest += int_change;
      principle += PmtAmt - int_change;

      if((cnt % i['PeriodComp']) == 0 || cnt == Periods){
         Adata1[Adata1.length] = interest;
         Adata2[Adata2.length] = principle;
         interest = principle = 0;
         }

      total -= PmtAmt - int_change;
      }

   //loan2//
   Interest2 = i['RateComp2']/(100*i['PeriodComp2']); //{i# = R / (100 * M) }
   Periods2 = i['YearsComp2'] * i['PeriodComp2']; //{N# = N# * M}
   Temp = Math.exp(-Periods2*Math.log(1+Interest2));
   PmtAmt2 = i['LoanCompAmt2']/((1-Temp)/Interest2);
   PaidAmt2 = PmtAmt2 * Periods2; //{XX# = X# * N#}

   Bdata1 = new Array();
   Bdata2 = new Array();
   total = i['LoanCompAmt2'];

   for(cnt=1;cnt<=Periods2;cnt++){
      int_change = (total * Interest2)<0?0:(total * Interest2);
      interest += int_change;
      principle += PmtAmt2 - int_change;

      if((cnt % i['PeriodComp2']) == 0 || cnt == Periods2){
         Bdata1[Bdata1.length] = interest;
         Bdata2[Bdata2.length] = principle;
         interest = principle = 0;
         }

      total -= PmtAmt2 - int_change;
      }


   //--- RESULTS API ASSIGNMENT ---//

   //loan 1//
   this.o['PmtAmt']  = currency(PmtAmt);
   this.o['RateComp']    = sprintf("%01.2f",i['RateComp']);
   this.o['LoanCompAmt'] = currency(i['LoanCompAmt']);
   this.o['IntPaid'] = currency(PaidAmt-i['LoanCompAmt']);
   this.o['YearsComp']   = i['YearsComp'];
   this.o['PeriodComp']  = i['PeriodComp'];

   var graph = new Graphite();
   graph.title = "Loan 1 Payments";
   graph.bar_padding = 0;
   graph.padding = 5;
   graph.y_width = 80;
   graph.x_label = 'Years';
   graph.y_label = 'Amount Paid';
   graph.add_list(Adata1,'Interest','');
   graph.add_list(Adata2,'Principal','');
   this.o['loan_comparison_graph1'] = graph.create();

   //loan 2//
   this.o['PmtAmt2']  = currency(PmtAmt2);
   this.o['RateComp2']    = sprintf("%01.2f", i['RateComp2']);
   this.o['LoanCompAmt2'] = currency(i['LoanCompAmt2']);
   this.o['IntPaid2'] = currency(PaidAmt2-i['LoanCompAmt2']);
   this.o['YearsComp2']   = i['YearsComp2'];
   this.o['PeriodComp2']  = i['PeriodComp2'];

   var graph = new Graphite();
   graph.title = "Loan 2 Payments";
   graph.bar_padding = 0;
   graph.padding = 5;
   graph.y_width = 80;
   graph.x_label = 'Years';
   graph.y_label = 'Amount Paid';
   graph.add_list(Bdata1,'Interest','');
   graph.add_list(Bdata2,'Principal','');
   this.o['loan_comparison_graph2'] = graph.create();
}


/******************************************************
 * Mortgage Payment
 */

_CJS['Mortgage Payment'] = new CashulatorJS('Mortgage Payment');
_CJS['Mortgage Payment'].eval = function(i){

   AmtToPay = i['MortAmt'];
   Interest = i['MortRate']/(100*i['MortPeriod']); //{i# = R / (100 * M) }
   Periods = i['MortYears'] * i['MortPeriod']; //{N# = N# * M}
   Temp = Math.exp(-Periods*Math.log(1+Interest));
   PmtAmt = AmtToPay/((1-Temp)/Interest);
   PaidAmt = PmtAmt * Periods; //{XX# = X# * N#}

   data1 = new Array();
   data2 = new Array();
   total = AmtToPay;

   var interest = principle = 0;

   for(cnt=1;cnt<=Periods;cnt++){
      int_change = (total * Interest)<0?0:(total * Interest);
      interest += int_change;
      principle += PmtAmt - int_change;

      if((cnt % i['MortPeriod']) == 0 || cnt == Periods){
         data1[data1.length] = interest;
         data2[data2.length] = principle;
         interest = principle = 0;
         }

      total -= PmtAmt - int_change;
      }

   //--- RESULTS API ASSIGNMENT ---//

   this.o['PmtAmt']  = currency(PmtAmt);
   this.o['MortRate']    = sprintf("%01.2f", i['MortRate']);
   this.o['MortAmt'] = currency(i['MortAmt']);
   this.o['IntPaid'] = currency(PaidAmt-AmtToPay);
   this.o['MortYears']   = i['MortYears'];
   this.o['MortPeriod']  = i['MortPeriod'];

   var graph = new Graphite();
   graph.title = "Mortgage Payments";
   graph.bar_padding = 0;
   graph.padding = 5;
   graph.y_width = 80;
   graph.x_label = 'Years';
   graph.y_label = 'Amount Paid';
   graph.add_list(data1,'Interest','');
   graph.add_list(data2,'Principal','');
   this.o['mortgage_graph'] = graph.create();

}

/******************************************************
 * Retirement Goal
 */

_CJS['Retirement Goal'] = new CashulatorJS('Retirement Goal');
_CJS['Retirement Goal'].eval = function(i){

  years = i['end_age'] - i['start_age'];

  future_goal = i['retirement_goal'] * Math.pow(1+(i['inflation']/100),years);
  r = i['interest']/1200;
  months = years*12;
  if(years==0){
  	monthly_save = investment_goal;
  	}
  else if (i['interest'] == 0){
  	monthly_save = (future_goal/(years*12));
  	}
  else{
  	monthly_save = ((future_goal*r)/((Math.pow(r+1,months))-1));
  	}

  //create graph//

  data1 = new Array();
  data2 = new Array();
  total = vint = saved = 0;

  for(cnt=1;cnt<=(years*12);cnt++){
  	int_change = total * r;
  	vint += int_change;
  	saved += monthly_save;

  	if((cnt % 12) == 0){
  		data1[data1.length] = vint;
  		data2[data2.length] = saved;
  		}

  	total = saved + vint;
  	}

  //--- RESULTS API ASSIGNMENT ---//
  this.o['retirement_goal']  = currency(i['retirement_goal']);
  this.o['interest']    = sprintf("%01.2f", i['interest']);
  this.o['inflation']    = sprintf("%01.2f", i['inflation']);
  this.o['future_goal']  = currency(future_goal);
  this.o['future_goal2']  = currency(future_goal);
  this.o['years']   = years;
  this.o['start_age']   = i['start_age'];
  this.o['end_age']   = i['end_age'];
  this.o['monthly_save'] = currency(monthly_save);

     var graph = new Graphite();
     graph.title = "Retirement Goal";
     graph.bar_padding = 0;
     graph.padding = 5;
     graph.y_width = 80;
     graph.label_offset = i['start_age'];
     graph.x_label = 'Age';
     graph.y_label = 'Amount Saved';
     graph.add_list(data1,'Interest','');
     graph.add_list(data2,'Principal','');
     this.o['retirement_goal_graph'] = graph.create();

}


/******************************************************
 * Saving
 */

_CJS['Saving'] = new CashulatorJS('Saving');
_CJS['Saving'].eval = function(i){

   Interest = i['Rate']/(100*i['Period']); //{i# = R / (100 * M) }
   Periods = i['Years'] * i['Period']; //{N# = N# * M}
   PaidAmt = i['PmtAmt'] * Periods; //{XX# = X# * N#}
   EndAmt = ((i['PmtAmt'] * (Math.exp(Periods*Math.log(1+Interest))-1))/Interest)*(1+Interest);

   data1 = new Array();
   data2 = new Array();
   total = interest = saved = 0;

   for(cnt=1;cnt<=Periods;cnt++){
      int_change = total * Interest;
      interest += int_change;
      saved += parseFloat(i['PmtAmt']);

      if((cnt % i['Period']) == 0 || cnt == Periods){
         data1[data1.length] = interest;
         data2[data2.length] = saved;
         }

      total = saved + interest;
      }


   //--- RESULTS API ASSIGNMENT ---//

   this.o['PmtAmt']  = currency(i['PmtAmt']);
   this.o['Rate']    = sprintf("%01.2f", i['Rate']);
   this.o['EndAmt']  = currency(EndAmt);
   this.o['EarnInt'] = currency(EndAmt-PaidAmt);
   this.o['Period']  = i['Period'];
   this.o['Years']   = i['Years'];

   var graph = new Graphite();
   graph.title = "Saving Results";
   graph.bar_padding = 0;
   graph.padding = 5;
   graph.y_width = 80;
   graph.x_label = 'Years';
   graph.y_label = 'Amount Invested<br />/Earned';
   graph.add_list(data1,'Interest','');
   graph.add_list(data2,'Principal','');

   this.o['savings_graph'] = graph.create();   

}