// initilize page variables

window.onerror=null
var bState = true;
var rec = 0;
var oTable = new Array();

// the colors for the amortization table... you will need to search and replace on these codes for the HTML form.
var bColor = '#FFFFFF' // white
var fColor = '#800080' //purple
// var fColor = '#008080' // green

// var bColor = 'WHITE'  // '#FFFFFF' 
// var fColor = 'PURPLE' // '#800080'


// names for the collections (used for form validation)
oReq = new Collection("AMOUNT","RATE","","","","")
oVal = new Collection("AMOUNT","RATE","","","","")
oTst = new Collection("N","N","","","","")


//============================================================================
// Gets called when the user pressed one of the buttons.
// oForm: 		form elements
// oBtn:  		the name of the button that was pressed
// return value:	did we make it through?
//============================================================================

function controller(oForm, oBtn) {

   while (bState) {

      if (!Required(oForm))

         break;

      if (!Validate(oForm))

         break;

      if (!Create())

         break;

      if (!SetValue(oForm))

         break;

      if (!Amortize(oForm, oBtn))

         break;

      if (bState) {

          bState = false

      }

   }

   bState = true

}



//============================================================================
// Check if a form element is required by comparing the all of the form
// elements against a collection of required form control names.
// oView: 		form elements
// oReq		required elements
// return value:	did it pass the test?
//============================================================================

function Required(oView) {

   for (i in oView ) {

      for (j in oReq) {

          if (i == oReq[j]) {      

             if (isMissing(oView[i])) {

               return(false)

             }

          }

      } 

  }

  return(true)

}



//============================================================================
// Check if a form control is required and missing
// oView: 		a form control
// Return value:	do we have a problem?
//============================================================================

function isMissing(oCtrl) {

   if (oCtrl.value == "") {  

      alert("You have left a required value blank. Please type a number");

      oCtrl.focus();

      oCtrl.select();

      return(true)

      }

   else

      { 

      return(false)

   }

}



//============================================================================
// Check if a form element inputs need to be a certain type by
// comparing all of the form elements against a collection of 
// form controls that need specific types of input data.
// oView: 		form elements
// oReq		required elements
// return value:	did it pass the test?
//============================================================================

function Validate(oView) {

   for (i in oView) {

      for (j in oVal) {

        if (i==oVal[j] && oTst[j]=="N") {      

           if (isTest(oView[i], oTst[j])) {

               return(false)

           }

        }

     }

  }

  return(true)

}



//============================================================================
// Check if a form control input is the right type
// oView: 		a form control
// Return value:	do we have a problem?
//============================================================================

function isTest(oCtrl, oTest) {

   if (oTest=="N" && !isNumber(oCtrl.value) ) {

      alert(oCtrl.value+" contains an invalid character. Please type a number");

      oCtrl.focus();

      oCtrl.select();

      return(true)

      }

      else

      { 

      return(false)

   }

}



//============================================================================
// Check if the result is a number
// input: 		a texbox value
// Return value:	true / false
//============================================================================

function isNumber(input) {

var result = ""

var nperiods = 0;

   for (var i=0;i<input.length;i++) {

      var ch = input.substring(i, i+1);

      if (!isNaN(parseInt(ch))) {

         result = result + ch

      } 

      if (ch==".") {

        nperiods++;

      }

      if (nperiods==1){

         result = result + ch  

      }

   }

   if (result == ""){

     return(false);

   }

return(true)

}



//============================================================================
// Make a string input into a number
// input: 		a texbox value
// Return value:	a number
//============================================================================

function makeNumber(input) {

var result = ""

var nperiods = 0;

   for (var i=0;i<input.length;i++) {

       var ch = input.substring(i, i+1);

       var flag = true;

       if (!isNaN(parseInt(ch))) {

          result = result + ch

       }           

       if (ch==".") {

         nperiods++;

       }

       if (nperiods==1){

          result = result + ch  

       }

     }

  return(result)

}


//============================================================================
// Create a default instance of the object
// parm1:	Amount	- required
// parm2:	Rate		- required
// parm3:   	Term		- required
// parm4:	Payment
// parm5:	Interest
// parm6:	Frequency	- required
// parm7:	Periods
// return value:	did we create the oebject?
//============================================================================

function Create() {

   Mortgage = new Loan(50000, 8, 30, 0, 0, "Monthly", 0 );

   return(true)

}


//============================================================================
// Set the properties of the object based on form inputs
// oView: 		form elements
// return value:	did it get and set the properties?
//============================================================================

function SetValue(oView) {

   // get the properties mapped from the form

   Mortgage.Amount = makeNumber(oView.AMOUNT.value);

   // works like a masked edit
   oView.AMOUNT.value = calcRound(Mortgage.Amount);

   Mortgage.Rate = makeNumber(oView.RATE.value);

   Mortgage.Term = get_selection(oView.YEARS);

   Mortgage.Frequency = get_selection(oView.FREQUENCY);

   // set the number of periods
   Mortgage.calcPeriods();

   // set the monthly payment
   Mortgage.calcPayment();

   // set the total interest due
   Mortgage.calcInterest();

   // update the form view
   Show()

   return(true)

}


//============================================================================
// Amortize is called at the end of the controler loop and checks to see
// if the amortize button was pushed
// oForm: 		form elements
// oBtn:  		the name of the button that was pressed
// return value:	did we select the Amortize button?
//============================================================================

function Amortize(oForm, oBtn) {

   if (oBtn.name == "cmdCalc") {

      return(false)

   }

   if (confirm("An Amortization Table calculates the periodic payment breakdown for each specific category listed.")) {

      // need to create the table before you can show it
      createRecords();

      // display the table
      showAmortize(oForm);

      return(true)

    }

  return(false)

}



//============================================================================
// create Records computes the values associated with the Amortzation of a Mortgage Loan and 
// adds those values to a record in the Amortization table container array
// return value:	did we calculate all values to display in the Amortization?
//============================================================================

function createRecords(){

   // re-init the record counter and container array
   rec = 0;

   oTable = new Array();

   // initialize variables
   var currInt = 0;

   var currPrin = 0;

   prevBalance = Mortgage.Amount;

   InterestRate = ( Mortgage.Rate /100) / Mortgage.Periods;

   MonthlyPayment = Mortgage.Payment;

   //currStart = '1997';
   currStart = get_selection(document.MORTGAGE.START);
  
   // let the loops begin
   for(i=1;i<=30;i++) {

      for(j=1;j<=Mortgage.Periods;j++) {

         periodInt = prevBalance * InterestRate;

         periodPrin = MonthlyPayment - periodInt;

         currBal = prevBalance - periodPrin;

         currInt += periodInt;

         currPrin += periodPrin;

         prevBalance = currBal;

      }

      if( currBal <= 0 ){ 

         currBal = 0;

      }



      // set the parameters
      Year = currStart;
      Interest = calcRound(currInt);
      Principle = calcRound(currPrin);
      Balance = calcRound(currBal);

      // increment the container 
      rec++

      // add a record to the table
      addRecord(Year, Interest, Principle, Balance);

      // re-init the private variables
      currInt = 0;
      currPrin = 0;
      currStart = parseInt(currStart);
      currStart += 1;

      // are we done?
      if(currBal<=0) {

         return(true)

      }       

   }

   return (true)

}



//============================================================================
// Collection Constructor, a custom object to act as an array but provide
// more flexibility in the future.
//============================================================================

function Collection(item1, item2, item3, item4, item5, item6) {

   this.item1 = item1;

   this.item2 = item2;

   this.item3 = item3;

   this.item4 = item4;

   this.item5 = item5;

   this.item6 = item6;

}



//============================================================================
// Loan Constructor, defines what the Loan object will look like
// and how it will behave. 
//============================================================================

function Loan(Amount, Rate, Term, Payment, Interest, Frequency, Periods ) {

   this.Amount = Amount;

   this.Rate = Rate;

   this.Term = Term;

   this.Payment = Payment;

   this.Interest = Interest;

   this.Frequency = Frequency;

   this.Periods = Periods;

   this.calcPeriods = calcPeriods;

   this.calcPayment = calcPayment;

   this.calcInterest = calcInterest;

}



//============================================================================
// Loan object method that calculates the monthly payment for a mortgage loan in the US
//============================================================================

function calcPayment() {

   this.Payment = (this.Amount*((this.Rate/(1200))/(1-(Math.pow(1+(this.Rate/(1200)),((this.Term*12)*-1))))));



  // handle bi-weekly 

  if ( this.Periods == 26 ){

      this.Payment = this.Payment / 2;

   }

}



//============================================================================
// Loan object method that calculates the interest portion of a loan
//============================================================================

function calcInterest() {

   this.Interest = ((this.Payment*(this.Term*this.Periods))-this.Amount);

}



//============================================================================
// Loan object method that translates a selection drop down to a value
//============================================================================

function calcPeriods() {

   if (this.Frequency=="Monthly") { this.Periods=12 } else { this.Periods=26 }

}



//============================================================================
// Loan object method that shows the calculated amounts
//============================================================================

function Show(oView) {

   document.MORTGAGE.PAYMENT.value = calcRound(Mortgage.Payment)

   document.MORTGAGE.INTEREST.value = calcRound(Mortgage.Interest)

}



//============================================================================
// oRecord Constructor, defines what the Amortzation record looks like 
//============================================================================

function oRecord(Year, Interest, Principle, Balance){

   this.Year = Year;

   this.Interest = Interest;

   this.Principle = Principle;

   this.Balance = Balance;

}



//============================================================================
// addRecord defines how a record gets added to the container array
//============================================================================

function addRecord(Year, Interest, Principle, Balance){

   oTable[rec] = new oRecord(Year, Interest, Principle, Balance);

}



//============================================================================
// select_item Constructor, used to retrive the selected item from the dropdown 
// control on a form.
// name: 		form element name
// value:  		the value of the options that was selected
// return value:	selected item
//============================================================================

function select_item(name, value) {  

   this.name = name;

   this.value = value;

}



//============================================================================
// Common routine to retrieve the selected value from the drop down object
// select_object:	a drop down from control
// return value:	the selected objects name
//============================================================================

function get_selection(select_object) {   

   contents = new select_item();

   for(var i=0;i<select_object.options.length;i++)

      if(select_object.options[i].selected == true) {

        contents.name = select_object.options[i].text;

        contents.value = select_object.options[i].value;

      }      

   return(contents.name)

}



//============================================================================
// Common routine for rounding that also formats the results into US currency
// num: 		a number
// return value:  result is rounded and formated for currency $999,999.00
//============================================================================

function calcRound(num) {

   result="£"+Math.floor(num)+"." ;

   n = result.length;

   if (num>1000 && num<999999) {  

     result="£"+result.substring(1,n-4)+","+result.substring(n-4,n);

   }

   if (num>1000000) {  

     result = "£"+result.substring(1,n-7)+","+result.substring(n-7,n-4)+","+result.substring(n-4,n);

   }

   var cents=100*(num-Math.floor(num))+0.5;

   result += Math.floor(cents/10);

   result += Math.floor(cents%10);

   return(result)

}





//============================================================================
// A page specific routine to set the initial state when the page is reloaded.
//============================================================================

function setfocus() {   

   document.MORTGAGE.AMOUNT.focus();

   document.MORTGAGE.AMOUNT.select();

}

