// $Id: rifcalc.js,v 1.3.30.1 2008/11/04 16:02:59 derekl Exp $
//  
// The RIF Calculator Javascript engine
//  
// Ayinde Yakubu, Copyright (c) 2003, Unisen Inc
//
// Define all required functions
//
// Define the different selection types possible

var gMIN        = 0;
var gPERCENT    = 1;
var gSET_AMOUNT = 2;
var gAMORTIZED  = 3;

// Define global constants
var gMandatedAge = 69.0;
var gCutOffAge = 90.0;
var gLastAge   = 150.0;
var gAgeCount  = 32.0; 
var gCutoffYear = 1992.0;

// Define RIF withdrawal schedules
var gPre1992  = new Array(gAgeCount);
var gPost1992 = new Array(gAgeCount);
var gAges     = new Array(gAgeCount);
var gFundsPost1992 = false;



var gTheYear = new Array(100);
var gTheRIF  = new Array(100);
var gGrossPayment = new Array(100);

// list tax regimes  
var gQUEBEC = "quebec";
var gCANADA = "canada";

//Deduct with holding tax or not
var deductWHT = "true";

initializeTables();

//Initialize all tables
function initializeTables()
{
     initPre1992();
	 initPost1992();
	 initAges();
} 

// -- RIF withdrawal schedule  - ages
function initAges()
{ 
    for ( var i = 0; i < gAgeCount; i++)
	{
	     gAges[i] = i + gMandatedAge ;
    }
}

// --- 
// The pre 1992 RIF withdrawal schedule
// These figures are preset by the government
// ---
function initPre1992()
{
    gPre1992[0] = 4.76;
    gPre1992[1] = 5.00;
    gPre1992[2] = 5.26;
    gPre1992[3] = 5.56;
    gPre1992[4] = 5.88;
    gPre1992[5] = 6.25;
    gPre1992[6] = 6.67;
    gPre1992[7] = 7.14;
    gPre1992[8] = 7.69;
    gPre1992[9] = 8.33;
    gPre1992[10] = 8.53;
    gPre1992[11] = 8.75;
    gPre1992[12] = 8.99;
    gPre1992[13] = 9.27;
    gPre1992[14] = 9.58;
    gPre1992[15] = 9.93;
    gPre1992[16] = 10.33;
    gPre1992[17] = 10.79;
    gPre1992[18] = 11.33;
    gPre1992[19] = 11.96;
    gPre1992[20] = 12.71;
    gPre1992[21] = 13.62;
    gPre1992[22] = 14.73;
    gPre1992[23] = 16.12;
    gPre1992[24] = 17.92;
    gPre1992[25] = 20.00;
    gPre1992[26] = 20.00;
    gPre1992[27] = 20.00;
    gPre1992[28] = 20.00;
    gPre1992[29] = 20.00;
    gPre1992[30] = 20.00;
    gPre1992[31] = 20.00;
}

// ---
// The post 1992 RIF withdrawal schedule
// These figures are preset by the government
// ---
function initPost1992()
{
    gPost1992[0] = 4.76;
	gPost1992[1] = 5.00;
	gPost1992[2] = 7.38;
	gPost1992[3] = 7.48;
	gPost1992[4] = 7.59;
	gPost1992[5] = 7.71;
	gPost1992[6] = 7.85;
	gPost1992[7] = 7.99;
	gPost1992[8] = 8.15;
	gPost1992[9] = 8.33;
	gPost1992[10] = 8.53;
	gPost1992[11] = 8.75;
	gPost1992[12] = 8.99;
	gPost1992[13] = 9.27;
	gPost1992[14] = 9.58;
	gPost1992[15] = 9.93;
	gPost1992[16] = 10.33;
    gPost1992[17] = 10.79;
	gPost1992[18] = 11.33;
	gPost1992[19] = 11.96;
	gPost1992[20] = 12.71;
	gPost1992[21] = 13.62;
	gPost1992[22] = 14.73;
	gPost1992[23] = 16.12;
	gPost1992[24] = 17.92;
	gPost1992[25] = 20.00;
	gPost1992[26] = 20.00;
	gPost1992[27] = 20.00;
	gPost1992[28] = 20.00;
	gPost1992[29] = 20.00;
	gPost1992[30] = 20.00;
	gPost1992[31] = 20.00;
}



// ---
// The payment fraction rule. The formula used to calculate the minimum if the applicant
// is below 69 years
// -- 
function paymentsFraction(appAge)
{

    var age = parseFloat(appAge);
	if ( age < gCutOffAge ) 
	{
	    //alert ( "Age -> " + age );
		//alert ( "Cut off->" + gCutOffAge);
		
	    return ( 1.0 / ( gCutOffAge - age ));
	}
	else
	{
		//alert("FIXME: Confirm how age " + age + " should be handled");
		return (0);
    }
}

// ---
// The RIF withdrawal schedule. This is the mandated mininum withdrawal % contained
// in a table based on age and plan start date. The minimum age defined in the table
// is 69 and there are two types of plans pre- and post-1992 due to changes in legislation
// ---
function findWDSchedule(age, fundsPost1992)
{
   var pos = -1;  //Use a sentinel for values
   var val = 0.0;
   for ( var i = 0; i < gAgeCount; i++)
   {   
      var m_age = gAges[i];
      //alert("Table: " + m_age + " Incoming: " + age);
      
      if ( age == m_age ) 
	  {
	     pos = i;
		 break;
	  }
   }
   
   // Use the index to locate percentage
   if ( pos == -1 )
   {  
      //alert("The age " +  age + " is not within the range 69 - 100 ");
	   return (20.0); //Default percent for any age above 100
   }
   
   if (fundsPost1992 == "yes" || fundsPost1992 == "true")
   {
         val = gPost1992[pos];
   }
   else {
         val = gPre1992[pos];
   }
   return val;   
}


// ---
// The actual percentage used to calculate minimum withdrawal allowed. If the
// applicant is under the age of 69 use the payment fractions rule, otherwise
// use the RIF withdrawal schedule percentage
// ---
function rifWithdrawalPercent(age, fundsPost1992)
{
      //alert("Age: " + age);
      var val = 0.0;
      if ( age < gMandatedAge )
	  {
         val = paymentsFraction(age);
	  }
	  else
	  {
	    val = percent(findWDSchedule(age, fundsPost1992));
	  }
      //alert("Age-> " + age +" percent-> " + percent);

	  return (val);
}

// ---
//  Interest factor for the remainder of year 1
// ---
function yearOneIntrFactor( currentDate, expectedROR)
{  
	var daysLeftInYear1 = daysLeftInYear (currentDate);
	var daysInYear1 = getNumberOfDaysInYear(currentDate);
	//alert ("Current date-> " + currentDate);
	//alert ("ROR->" + expectedROR);
    var interestFactor = expectedROR  * (daysLeftInYear1 / daysInYear1 );	
	return interestFactor;
}


// ---
// The opening value of the Plan as of Jan 1st year two. This
// will include interest accrued for the partial year.
// ---
function yearOneRIFValue(startingBal, year1IntrFactor)
{
  //alert( "Starting Balance-> " + startingBal);
  //alert("Year One Interest Factor->" + year1IntrFactor);
  var result = startingBal * ( 1.0 + year1IntrFactor) ;   
   return ( result );  
}

// ---
// RIF Value. The opening value of the Plan as of Dec 31st that year
// ---
function calculateRIFValue(startingBal, expectedROR, rifWithdrawalAmt)
{ 
  //  alert ( "starting bal->" + startingBal + " rif with amt-> " +rifWithdrawalAmt );
    var result = startingBal * ( 1.0 + expectedROR ) - rifWithdrawalAmt;
    return result;
}


// ---
// RIF Minimum withdrawal. The minimum amount that must be withdrawn from the plan each
// year as mandated by government rules. Any amount in excess of this will be subject to
// provincial withholding tax.
// ---
function rifWithdrawalMinimum(startingBalance, rifWPercent)
{
    var result = new Number(startingBalance) * new Number(rifWPercent);
	return result;
}


// ---
// RIF Withdrawal Amount. This is dependent on the type of withdrawal. The applicant has
// three choices - Minimum, Percentage, or Amount
// ---
function rifWithdrawalAmount(selectionType, startingBalance, amount, rifIntrFactor, withdrawalPercent, toAge, currentAge)
{
   var withdAmount = 0.0;
   
   //alert ("Selection type: " + selectionType);
   //alert ("Amortization: " + amortizedPayment);
   if ( selectionType == gMIN )
   {
	   withdAmount = rifWithdrawalMinimum(startingBalance, rifIntrFactor);
   }
   else if ( selectionType == gPERCENT )
   { 
       withdAmount = startingBalance * withdrawalPercent;
       //alert("Percent - selection type - amount -" + withdAmount);
   }
   else if ( selectionType == gSET_AMOUNT )
   {
       withdAmount = amount;
   }       
   else if ( selectionType == gAMORTIZED )
   {
       //alert(selectionType);
       //alert(firstTimeAmortz);
        withdAmount = calculateRegularAmortization(startingBalance, toAge, currentAge);
   }
   
   //alert(withdAmount);
   
   return (withdAmount);
}


//---
// Calculate regular amortization. This is the normal amortization
// after first year amortization has been calculated.
//---
function calculateRegularAmortization(startingBalance, lastAge, currentAge)
{
    var sBal = parseFloat(startingBalance);
    var lAge = parseFloat(lastAge);
    var cAge = parseFloat(currentAge);
    if (lAge == cAge )
    {
       return 0.0;
    }
    
    var result = sBal/(lAge - cAge - 1.0);
    return result;
}

// Returns the plan description based on the selection type

function  getPlanDescr(selectionType)
{
     
     //alert ("Amortization: " + amortizedPayment);
     if ( selectionType == gMIN )
     {
  	   return "MINIMUM";
     }
     else if ( selectionType == gPERCENT )
     { 
         return "PERCENT";
     }
     else if ( selectionType == gSET_AMOUNT )
     {
         return "FIXED AMOUNT";
     }       
     else if ( selectionType == gAMORTIZED )
     {
         return "AMORTIZED";
     }
     return "UNKNOWN";
}


// ---
// Taxable Amount. The amount of withdrawal that is in excess of the minimum
// ---
function taxableAmount(rifWDAmount, rifMinAmount)
{
   return (rifWDAmount - rifMinAmount);
}

// ---
// Withholding tax amount. The amount of tax payable based on  applying a tax rate
// to the taxable amount. Based on a range and the province of residence since
// Quebec has a different rate than the other provinces.
// ---
function withHoldingTax(taxableAmount, taxRate)
{
    return ( taxableAmount * taxRate );
}


// --- 
// Calculate Quebec tax
// ---
function quebecTaxSchedule(amount)
{
    if ( amount >= 0.0 && amount <= 5000.0 )
	{
	    return (0.21);
	}
	else if ( amount > 5000.0 && amount <= 15000.0  )
	{
	    return (0.30);
	}
	else 
	{
	   return (0.35);
	}
}


// -- Calculate Non Quebec Tax
function canadaTaxSchedule(amount)
{
    
    if ( amount >= 0.0 && amount <= 5000.0 )
	{
	    return (0.10);
	}
	else if ( amount > 5000.0 && amount <= 15000.0  )
	{
	    //alert("Amount to withdraw: " + amount);
	    return (0.20);
	}
	else 
	{
	   return (0.30);
	}
}

// --- 
// Calculate taxable amount
// ---
function calculateTax(amount, province)
{
   var tax = 0.0;
   var taxrate = 0.0;
    
   if ( province != gQUEBEC )
   {
       //alert("[calculateTax] + amount: " + amount); 
       taxrate =  canadaTaxSchedule(amount);
   }
   else
   {
       taxrate = quebecTaxSchedule(amount);
   }
   tax = withHoldingTax(amount, taxrate);
   
   return (tax);
}

//---
// This calculates the first amortization of the series. The first
// amortization calculates growth due to improvement in the 
//
//---
function calculateAmortization(openingBalance, expROR, period, years)
{
    var result = 0.0;
    var interestRate = expROR / period;
    
    var totalYears = period * years;
    var compdIntr = Math.pow((1.0 + interestRate), totalYears);
    var tempOne = openingBalance * compdIntr * interestRate;
    
    var tempTwo = compdIntr - 1.0;
    result = tempOne / tempTwo;

    //alert("Amortized Payment: " + result);
    
    return result;

}

// ---
// Net Amount of withdrawal. The net amount of payment after applicable taxes have
// been withheld.
// ---
function netAmountWithdrawal(rifWdAmount, withHoldingTx)
{
     return (rifWdAmount - withHoldingTx);
}


// ---
// Determine the payment type selection that is made by the client
// ---
function OnChange(myForm)
{
   var myindex  = myForm.txtSelectionGroup.selectedIndex;
   var selValue = myForm.txtSelectionGroup.options[myindex].value;

   if ( selValue == "MIN" )
   {
       myForm.txtAmount.disabled = true;
       myForm.txtPercent.disabled = true;
       myForm.txtAmount.value ="0.0";
       myForm.txtPercent.value = "0.0";
   }
   else if ( selValue == "PERCENT" )
   {
       myForm.txtAmount.disabled = true;
       myForm.txtAmount.value = "0.0";
       myForm.txtPercent.disabled = false;
       myForm.txtPercent.value = "0.0";
   }
   else if( selValue == "FIXED" )
   
   {
       myForm.txtAmount.disabled = false;
       myForm.txtPercent.disabled = true;
       myForm.txtPercent.value = "0.0";
       myForm.txtAmount.value = "0.0";
   }
   else if(selValue == "AMORTIZED")
   {
       myForm.txtAmount.disabled = true;
       myForm.txtPercent.disabled = true;
       myForm.txtAmount.value ="0.0";
       myForm.txtPercent.value = "0.0";

   }
   myForm.txtSelectionType.value=selValue;
}

// --
// Process the payment selection type. Converts the string to int values
// FIXME. It might be better to use a simple lookup table here
//
// --- 
function identifySelectionType(str)
{
    if ( str == "MIN" )
	{
	   return gMIN;
	}
	else if ( str == "PERCENT" )
	{
	   return gPERCENT;
	}
	else if ( str == "FIXED" )
	{
	   return gSET_AMOUNT;
	}
	else if (str == "AMORTIZED" )
	{
	   return gAMORTIZED;
	}
	else
	{
	   return alert("You must select a payment type");
	}
}

// ---
// Identify the client's residence for tax purposes
// ---
function evaluateResidence(value)
{    
   var prov = "";
   
   if ( value == "yes" )
   {
      prov = gQUEBEC;
   }
   else
   {
     prov = gCANADA;
   }
   return prov;
 }

//
// ---
// This method is called by the html forms. It checks that inputs are valid,
// converts them from text to appropriate items, and then call the RIF calculator. The
// RIF calculator expects correct data type
// ---
function runRIF(myForm)
{
   //parse date of birth
   var dob=myForm.txtBirthDate.value;

   var dateOfBirth = stringToDate(dob);
   if (dateOfBirth == null || dateOfBirth == false)
   {
      myForm.txtBirthDate.focus();
      return false;
   }

   var issdate=myForm.txtIssueDate.value;
   var issueDate=stringToDate(issdate);
   if (issueDate == null || issueDate == false)
   {
      myForm.txtIssueDate.focus();
      return false;
   }
   
   var expectedROR=preparePercent(myForm.txtROR.value);
   var lastAge = prepareNumber(myForm.txtToAge.value);
   var startingBalance = prepareNumber(myForm.txtPlanValue.value);
   var selectionType = identifySelectionType(myForm.txtSelectionType.value);
   
   //FIXME - Code this within the form
   var period = prepareNumber(myForm.paymentFreq.value);
   // alert ("Period: " + period);
   var deductWHT = myForm.deductWithTax.value;

   var province = evaluateResidence(myForm.quebecResident.value);
   //alert(province);
   
   var post1992 = myForm.post1992Fund.value;
   //alert(post1992);
   
   var annualWithPercent=0.0;
   var annualWithAmount=0.0;

   annualWithPercent=preparePercent(myForm.txtPercent.value);
   annualWithAmount=prepareNumber(myForm.txtAmount.value);

   rifCalculator(dateOfBirth, expectedROR, lastAge, issueDate, startingBalance, selectionType, deductWHT,annualWithPercent, annualWithAmount, post1992, province, period);
}




function beginRIFBody()
{
  document.write("<BODY BGCOLOR='#ffffff' MARGINWIDTH='5' MARGINHEIGHT='5' LEFTMARGIN='5' TOPMARGIN='5'>");
  document.write("<TABLE WIDTH='100%' CELLSPACING='0' CELLPADDING='0' BORDER='0'>");
  document.write("<TR>");
  document.write("<TD> <TABLE WIDTH='100%' class='page-header-table'><TR><TD class='page-header-td'>RIF Illustrator</TD></TR></TABLE></TD>");
  document.write("</TR>");
  document.write("<TR><TD>&nbsp;</TD></TR>");
  document.write("<TR>");
  document.write("<TD WIDTH='100%'><P CLASS='textpad-notopmarg' align='right'>");
  document.write("<A CLASS=\"underline\" href='javascript:showHelp()'><img src=\"image/help.gif\" border=\"0\">Help</a>");
  document.write("<img src=\"images/dot.gif\" border=\"0\" height=\"1\" width=\"20\">");
  document.write("<A CLASS=\"underline\" href='rifcalc.zip'><img src=\"image/download.gif\" border=\"0\">Download</A>");
  document.write("<img src=\"images/dot.gif\" border=\"0\" height=\"1\" width=\"20\">");
  document.write("<A CLASS=\"underline\" HREF=\"#\" ONCLICK=\"decreaseFontSize();return false;\"><img src=\"image/font_minus.gif\" border=\"0\">Font</a>");
  document.write("<img src=\"images/dot.gif\" border=\"0\" height=\"1\" width=\"20\">");
  document.write("<A CLASS=\"underline\" HREF=\"#\" ONCLICK=\"increaseFontSize();return false;\"><img src=\"image/font_plus.gif\" border=\"0\">Font</a>");
  document.write("<img src=\"images/dot.gif\" border=\"0\" height=\"1\" width=\"20\">");
  document.write("<a CLASS=\"underline\" href=javascript:window.print()><img src='image/btn_print.gif' border='0'> Print</a>");
  document.write("<img src=\"images/dot.gif\" border=\"0\" height=\"1\" width=\"20\">");  
  document.write("</P></TD>");
  document.write("</TR>");
  document.write("<TR>");
  document.write("<TD WIDTH='100%'><P CLASS='textpad-notopmarg'>This calculator determines the income stream available for a Registered Income Fund in retirement.</P></TD>");
  document.write("</TR>");
  document.write("<TR>");
  document.write("<TD WIDTH='100%' align='center'>");
  // document.write("<table width='80%' border='0' cellpadding='0' cellspacing='10'>");
  document.write("<TABLE WIDTH='100%' CELLSPACING='0' CELLPADDING='0' BORDER='1' BORDERCOLOR='#DCDCDC'>");
  document.write("<tr>");
  document.write("<TD COLSPAN='12' class='headpad-gray-px11-subheader'>RIF ILLUSTRATOR RESULTS</td>");
  document.write("</tr>");
  document.write("<TR><TD COLSPAN='12'><IMG SRC='image/dot.gif' WIDTH='1' HEIGHT='5' ALT='' BORDER='0'></TD</TR>");
  //document.write("</table>");
  //document.write("<table width='100%' border='0' cellpadding='0' cellspacing='0'>");
  //document.write("<TR>");
  //document.write("<TD BGCOLOR='#E6E5E5'>");
  //document.write("<table width='100%' border='0' cellpadding='1' cellspacing='1'>");
}


function endRIFBody()
{
 // document.write("</TD>");
  //document.write("</TR>");
 // document.write("</TABLE>");
  document.write("</TD>");
  document.write("</TR>");
  document.write("<TR>");
  document.write("<TD WIDTH='780'>");
  document.write("<TABLE WIDTH='600' CELLSPACING='0' CELLPADDING='0' BORDER='0' ALIGN='center'>");
  document.write("<TR>");
  document.write("<TD COLSPAN='13'><IMG SRC='image/dot.gif' WIDTH='1' HEIGHT='40' ALT='' BORDER='0'></TD>");
  document.write("</TR>");
  document.write("<TR>");
  document.write("</TR>");
  document.write("<TR>");
  document.write("<TD COLSPAN='13'><IMG SRC='image/dot.gif' WIDTH='1' HEIGHT='10' ALT='' BORDER='0'></TD>");
  document.write("</TR>");
  document.write("</TABLE>");
  document.write("</BODY>");
}


// ---
// Write the table's header
//
function writeHeader()
{
       beginHeaderRow();
	   
       beginHeaderRowData();
       document.write("<b>AGE</b>"); 
       endHeaderRowData();

       beginHeaderRowData();
       document.write("<b>YEAR</b>");
       endHeaderRowData();

	   //beginHeaderRowData();
	   //document.write("Payment Fraction");	   
	   //endRowData();

       beginHeaderRowData();
       document.write("<b>OPENING VALUE</b>");
       endHeaderRowData();

	   //beginRowData();
	   //document.write("<b>Opening Value</b>");
	   //endRowData();

       //beginHeaderRowData();
       //document.write("<b>RIF Value</b>");
       //endHeaderRowData();

       //beginHeaderRowData();
       //document.write("Withdrawal Schedule \%");
       //endRowData();

       //beginHeaderRowData();
       //document.write("Withdrawal \%");
       //endRowData();

       beginHeaderRowData();
       document.write("<b>GROSS PAYMENT</b>");
       endHeaderRowData();
 

       beginHeaderRowData();
       document.write("<b>PAYMENT per PERIOD</b>");
       endHeaderRowData();

       beginHeaderRowData();
       document.write("<b>MINIMUM AMOUNT</b>");
       endHeaderRowData();

       beginHeaderRowData();
       document.write("<b>TAXABLE AMOUNT</b>");
       endHeaderRowData();

       beginHeaderRowData();
       document.write("<b>WITHHOLDING TAX</b>");
       endHeaderRowData();

       beginHeaderRowData();
       document.write("<b>NET PAYMENT</b>");
       endHeaderRowData();

      endRow();
}

function writeLinks(title, link)
{

 // alert("<a href= \"" + link + "\">" + title + "</a>");
  document.write("<a href=\"/" + link +"\">" + title +"</a>");
  
  
}

// Print a new line for the specified number of times
function newLine(times)
{

   var loopEnd = 0.0;
   var val = parseInt(times);
   // alert (val);
   if ( isNaN(val) == true )
   {
       loopEnd = 1.0;
   }
   
   for ( i = 0 ; i < loopEnd; i++ )
   {
          document.write("<br>");
   }
}

//-- 
// End the table tag
//-- 
function endTable()
{
   document.write("</table>");
}

function beginRow()
{
  document.write("<tr>");
}

function beginHeaderRow()
{
  document.write("<tr VALIGN='top' bgcolor='#FFCC66'>");
}

function beginRowWhite()
{
  document.write("<tr class='data-row-white'>");
}

function beginRowGray()
{
  document.write("<tr class='data-row-gray'>");
}

function endRow()
{
  document.write("</tr>");
}

function beginHeaderRowData()
{
  document.write("<td class='headpad-yellow-col-left'>");
}

function endHeaderRowData()
{
  document.write("</td>");
}

function beginForm()
{
  document.write("<form name=myForm>");
}

function endForm()
{
   document.write("</form>");
}
   
function beginRowData()
{
  document.write("<td class='data-row-detail-right'>");
}

function beginRowResultData()
{
  document.write("<td align='left'>");
}

function endRowData()
{
  document.write("</td>");
}

// ---
//  Calculate the rif table
// ---
function rifCalculator(dateOfBirth, expectedROR, toAge, issueDate, startingBalance, 
                       selectionType, deductWHT, annualWithPercent, annualWithAmount, fundsPost1992, province, period)
{
   //Calculate current age and age at issue date
   var currentAge = calculateAge(dateOfBirth, new Date());
   if ( currentAge == 0 )
   {
      return;
   }
   
   //Always start a year earlier
   var startAge = calculateAge(dateOfBirth, issueDate);
   if ( startAge == 0 )
   {
      return ;
   }
   
   //Calculate initial percentage of the year
   var yearOneFactor = yearOneIntrFactor(issueDate, expectedROR);
   var planValue = startingBalance;
   var yearOneOpeningBal = yearOneRIFValue(startingBalance, yearOneFactor);

   var startYear = issueDate.getFullYear();

   //If no end age specified, assume hundred   
   var lastAge = parseFloat(toAge);
   //alert ("toAge->" + lastAge );
  
   lastAge = (lastAge > 0) ? lastAge: 100.0;
   var year = startYear;
   var endAge = lastAge;
   var taxableAmt = 0.0;
   var withHoldingTax = 0.0;
   var rifValue = 0.0;
   var withdAmount = 0.0;
   var withIntr = 0.0;
   var annualP =  annualWithPercent;
   
   var minAmount = 0.0;
   var age = startAge;
   var pymntFraction = 0.0;
   
   var netPayment = 0.0;
   var lastRifValue = 0.0;
   //
   
   //Accumulate total values
   var totalPayments = 0.0;
   var totalWithHoldingTax = 0.0;
   var totalNetPayment = 0.0;
   startingBalance = yearOneOpeningBal;
   
   //Initial the payment per period value
   var paymentPerPeriod = 0.0;
   //alert(period);
   // Calculate amortized payment
   //
   var amortizedPayment = 0.0;
   var totalYears = Math.round(toAge - startAge);
  
   
   beginHtml("RIF ILLUSTRATOR RESULTS");
   beginRIFBody();
   
   writeHeader();
	
   var colorIdx = 0;
   var j = 0;
   var firstTimeAmortz = false;
 
   var amortz = 0.0;
   
   // The first time amortization is calculated is different for all
   // other times. 
   if ( selectionType == gAMORTIZED )
   {
         //alert("First Time:");
         amort = calculateAmortization(startingBalance, expectedROR, period, totalYears);
         withdAmount = amort * period;
         
         //alert ("Starting Balance: " + startingBalance + " First Amortized Payment: " + withdAmount);
         regularAmort = false;
         //startAge = startAge;
   }
   
   
   //Regular time through loop  
   for ( var i = startAge; i <= endAge; i++ )
   {   

       tempAge = age - 1;    
       pymntFraction = paymentsFraction(tempAge);
	   //alert(pymntFraction);
	   rifWithdSchedule=percent(findWDSchedule(tempAge, fundsPost1992));
	   
	   //alert(rifWithdSchedule);
	   withIntr = rifWithdrawalPercent(age-1, fundsPost1992);
	   //alert("Withdrawal Intr: "  + withIntr + " Age: " + tempAge );

	   //alert(withIntr);
       minAmount = rifWithdrawalMinimum(startingBalance, withIntr);
       //alert("Min Amount: " + minAmount);

       if( selectionType == gAMORTIZED )
       {
          if( regularAmort == true )
          {
             withdAmount = rifWithdrawalAmount(selectionType, startingBalance, annualWithAmount, withIntr, annualP,endAge,tempAge);
          }
       }
       else
       {
          withdAmount = rifWithdrawalAmount(selectionType, startingBalance, annualWithAmount, withIntr, annualP,endAge,tempAge);       
       }
    

       //alert ("Withdrawal Amount: " + withdAmount);
       //if ( tempAge == 73 )
      // {
        //   alert("Wrong values..." + withdAmount);
       //}
       
	   if ( minAmount > withdAmount) 
	   {
	       withdAmount = minAmount;
	   }

	   rifValue = calculateRIFValue(startingBalance, expectedROR, withdAmount);
	   
	
	   if ( startingBalance < withdAmount )
	   {
		  withdAmount = startingBalance;
	   }

	   //Prevents the RIF from being less than zero
	   lastRifValue = rifValue;
	   if ( startingBalance < 0 )
	   {
	       break;
	   }


	   taxableAmt = taxableAmount(withdAmount, minAmount);
	   //Only deduct withholding tax if requested by the client
	   if ( deductWHT == "yes" )
	   {
	       //alert("Taxable Amount: " + taxableAmt);
	   	   withHoldingTax = calculateTax(taxableAmt, province);
	   }
	   else
	   {
    	  withHoldingTax = 0.0;
       }
	   
       //     Age, Year, Payment fraction rules %, Opening Value, RIF Value, RIF withdrawal schedule %, 
       //      Rif withdrawal %, RIF withdrawal amount, Min. withdrawal amount, Taxable Amount, Quebec, Other
       if (colorIdx%2==0) {	
       	beginRowWhite();
       } else {
       	beginRowGray();
       }

	   beginRowData();
	   document.write(age); 
	   endRowData();
	   
       year = startYear + i - startAge ;
	   beginRowData();
	   document.write(year);
	   gTheYear[j] =  year;
	   endRowData();

	   //beginRowData();
	   //document.write(formatNumber(pymntFraction, 4));	   
	   //endRowData();

	   beginRowData();
	   document.write(convertToMoney(startingBalance));
	   gTheRIF[j]  = startingBalance;
	   endRowData();

	   //beginRowData();
	   //document.write("Opening Value");
	   //endRowData();

	 //  beginRowData();
	 //  document.write(convertToMoney(rifValue));
	 //  endRowData();

	   //beginRowData();
	   //document.write(formatNumber(rifWithdSchedule, 4));
	   //endRowData();

	   //beginRowData();
	   //document.write(formatNumber(withIntr, 5));
	   //endRowData();

	   beginRowData();
	   document.write(convertToMoney(withdAmount));
	   gGrossPayment[j] = withdAmount;
	   endRowData();

       //Payment per period
       paymentPerPeriod = withdAmount/period;
       
	   beginRowData();
	   document.write(convertToMoney(paymentPerPeriod));
	   endRowData();
      
	   beginRowData();
	   document.write(convertToMoney(minAmount));
	   endRowData();

	   beginRowData();
	   document.write(convertToMoney(taxableAmt));
	   endRowData();

	   beginRowData();
	   document.write(convertToMoney(withHoldingTax));
       endRowData();


	   beginRowData();
	   netPayment = withdAmount - withHoldingTax;
	   //alert(netPayment);
	   document.write(convertToMoney(netPayment));
	   endRowData();
	   
	   //Increase age by 1
	   age++;
	   startingBalance = rifValue;
	   j++;
           
           
       //Accummulate core values
       totalPayments = new Number(totalPayments) + new Number(withdAmount);
	   totalWithHoldingTax = new Number(totalWithHoldingTax) + new Number(withHoldingTax);
	   totalNetPayment = new Number(totalNetPayment) + new Number(netPayment);

	   endRow();
       
       //After first amortization is calculated, the 	   
	   regularAmort = true;
	   
	   colorIdx = colorIdx + 1;
   }

  // endTable();
  // newLine(4);
   
   //beginTable("Totals")
   if (colorIdx%2==0) {	
   	beginRowWhite();
   } else {
   	beginRowGray();
   }
   colorIdx = colorIdx + 1;
 
   //Display total variables
   // beginRowData(); 
   document.write("<TD COLSPAN='8'>"); 
   document.write("<DIV ALIGN='left' class='grey-bold'>Total Payments:</DIV>"); 
   
   endRowData();

   beginRowData();
  
   //alert("Total payments: " + totalPayments);
   document.write("<DIV ALIGN='right' class='table-text-bold'>");
   document.write(convertToMoney(totalPayments)); 
   document.write("</DIV>");
   var tmpWithHoldingTax = convertToMoney(totalWithHoldingTax);
   var tmpGrossIncome = convertToMoney(totalPayments);
   
   endRowData();
   endRow();

   // beginRow()
   if (colorIdx%2==0) {	
   	beginRowWhite();
   } else {
   	beginRowGray();
   }
   colorIdx = colorIdx + 1;
  // beginRowData();
   document.write("<TD COLSPAN='8'>"); 
   document.write("<DIV ALIGN='left' class='grey-bold'>Total Withholding Tax:</DIV>");
   endRowData();

   beginRowData();
   document.write("<DIV ALIGN='right' class='table-text-bold'>");
   document.write(convertToMoney(totalWithHoldingTax));
   document.write("</DIV>");
   var tmpWithHoldingTax = convertToMoney(totalWithHoldingTax);
   
   endRowData();
   endRow();
   
   //beginRow();
   if (colorIdx%2==0) {	
   	beginRowWhite();
   } else {
   	beginRowGray();
   }
   colorIdx = colorIdx + 1;
   // beginRowData();
   document.write("<TD COLSPAN='8'>"); 
   document.write("<DIV ALIGN='left' class='grey-bold'>Total Net Payments:</DIV>");
   endRowData();

   beginRowData();
   document.write("<DIV ALIGN='right' class='table-text-bold'>");
   document.write(convertToMoney(totalNetPayment));
   document.write("</DIV>");
   var tmpNetIncome = convertToMoney(totalNetPayment);
   
   endRowData();
   endRow();

   var tmpLastAge = endAge;
   var tmpLastRifValue =convertToMoney(lastRifValue);
   //alert ( "Last Rif Value: " +myForm.txtLastRifValue);
   endTable();
   
	
   //writeLinks("Summary","javascript:runRIFSummary(myForm)");
   //var params = createParamsArray(myForm);
   //function rifCalculator(dateOfBirth, expectedROR, toAge, issueDate, startingBalance, 
   //                       selectionType, deductWHT, annualWithPercent, annualWithAmount, fundsPost1992, province, period, myForm)

   var params = new Array(20);
   params[0] = deductWHT

   params[1]="yes";
   if (province=="canada")
   {
      params[1] = "no";
   }
   params[2] = fundsPost1992
   params[3] = planValue;
   params[4] = getPlanDescr(selectionType);
   params[5] = expectedROR;
   params[6] = dateOfBirth;
   params[7] = issueDate;
   params[8] = toAge
   params[9] = annualWithPercent
   params[10] = tmpGrossIncome;
   params[11] = tmpWithHoldingTax;
   params[12] = tmpNetIncome;
   params[13] = tmpLastAge;
   params[14] = tmpLastRifValue;
   var strParams = makeParams(params);

   document.write("<TR>");
   document.write("<TD WIDTH='532' align='right'>&nbsp;<br>");
   
   document.write(" ");
   document.write("<strong>RESULT SUMMARY</strong>");
   
   document.write("</TD>");
   document.write("</TR>");
   
   
   document.write("<TR>");
   document.write("<TD>");
   
   //Call the summary method
   runRIFSummary(strParams);

   endRIFBody();
   endHtml();
	
	// In FireFox/Safari, reload() function does not work. This is a workaround until the application is rewriten.
   	if ((/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) || (/Safari/.test(navigator.userAgent))) { //test for Firefox/x.x or Firefox x.x (ignoring remaining digits) and Safari;	
		//window.location.reload();
	} else {
		window.location.reload();
	}
}

// --
// Plot the Gross payment graph
// --
function createParamsArray(myForm)
{
   var params = new Array();
   params[0] = myForm.deductWithTax.value;
   params[1] = myForm.quebecResident.value;
   params[2] = myForm.post1992Fund.value;
   params[3] = myForm.txtPlanValue.value;
   params[4] = myForm.txtSelectionType.value;
   params[5] = myForm.txtROR.value;
   params[6] = myForm.txtBirthDate.value;
   params[7] = myForm.txtIssueDate.value;
   params[8] = myForm.txtToAge.value;
   params[9] = myForm.txtPercent.value;
   params[10] = myForm.txtGrossIncome.value;
   params[11] = myForm.txtWithHoldingTax.value;
   params[12] = myForm.txtNetIncome.value;
   params[13] = myForm.txtLastAge.value;
   params[14] = myForm.txtLastRifValue.value;
   return params;
   
}