function amortizer(principal, rate, termYears) {
  this.minBal = 7500;
  
  this.validInterest = false;
  this.validPrincipal = false;
  this.validTermYears = false;
  
  this.onePercentOff = false;
  this.onePercentOffStart = 36;
  this.ach = false;
                             
  this.isValid = amortizer_isValid;
  this.validatePrincipal = amortizer_validatePrincipal;
  this.validateInterest = amortizer_validateInterest;
  this.validateTermYears = amortizer_validateTermYears;
  this.getPrincipal = amortizer_getPrincipal;
  this.getInterest = amortizer_getInterest;
  this.getTermYears = amortizer_getTermYears;
  this.getInterval = amortizer_getInterval;
  this.getDecimalInterest = amortizer_getDecimalInterest;
 
  this.getMonthlyPayment = amortizer_getMonthlyPayment;
  this.setMonthlyPayment = amortizer_setMonthlyPayment;
  this.getBalance = amortizer_getBalance;
  this.getInterestBalance = amortizer_getInterestBalance;
  this.getInterestOnlyMonthlyPayment = amortizer_getInterestOnlyMonthlyPayment;
  
  this.getRemainingPrincipal = amortizer_getRemainingPrincipal;
  this.getPrincipalPaidThisPayment = amortizer_getPrincipalPaidThisPayment;
  this.getSchedule = amortizer_getSchedule;
  this.getRemainingAmortizer = amortizer_getRemainingAmortizer;
  this.setSchedule = amortizer_setSchedule;
  this.setOnePercentOff = amortizer_setOnePercentOff;
  this.setOnePercentOffStart = amortizer_setOnePercentOffStart;
  this.setACH = amortizer_setACH;

  this.setTermYears = amortizer_setTermYears;

  this.principal = this.validatePrincipal(principal);
  this.interest = this.validateInterest(rate);
  this.years = this.validateTermYears(termYears);
  this.valid = (this.validInterest & this.validPrincipal & this.validTermYears);
  
  this.decimalInterest = (this.interest / 100);
  this.interestDiscount = 0;

  // this.interval = 365/31;  //Do things the AES way
  this.interval = 12; //do things the standard way
 
  this.monthlyPayment = 0;
  this.balance = 0;
  this.interestBalance = 0;
  this.totalInterestPaid = 0; //used when calculating interest paid during savings deduction payments.
  this.interestOnlyMonthlyPayment = 0;  
  this.schedule = new paymentSchedule();

}

function amortizer_getPrincipal() {
  return this.principal;
}
function amortizer_getInterest() {
  return this.interest;
}
function amortizer_getTermYears() {
  return this.years;
}
function amortizer_getInterval() {
  return this.interval;
}
function amortizer_getDecimalInterest() {
  return this.decimalInterest;
}
function amortizer_isValid() {
  return this.valid;
}
  


function amortizer_setOnePercentOff(mybool) {
  if (this.principal >= 20000) {
    this.onePercentOff = mybool; 
  }
}

function amortizer_setOnePercentOffStart(myInt) {
  if (this.principal >= 20000) {
    this.onePercentOffStart = myInt;
  }
}

function amortizer_setACH(mybool) {
  //  if (this.principal >= 20000) {
    this.ach = mybool;
    // }
}

function amortizer_validatePrincipal(num) {
  num = parseFloat(num.toString().replace(/\$|\,/g,''));
  if (isNaN(num)) {
    alert("Please enter a valid Consolidation Loan Amount");
    return num;
  } else { 
    this.validPrincipal = true; 
    return num;  
  }
}
  
function amortizer_validateInterest(num) {
  num = parseFloat(num.toString().replace(/\$|\,/g,''));
 
  if (isNaN(num) || num > 24 || num < 0) {
    alert("please enter a consoldation interest rate above zero, but below 24%");
    return NaN;
  } else {
    
    this.validInterest = true;
    return num;
  }

}

function amortizer_validateTermYears(num) {
  num = Math.round(parseFloat(num.toString().replace(/\$|\,/g,'')))
    if (isNaN(num) || !(num > 0)) {
      alert("Please enter a valid Loan Term (in years)");
      return num;
    } else {
      this.validTermYears = true; 
      return num;
    } 
}

function amortizer_getMonthlyPayment(myPayment) {
  if (this.valid) {
    if (isNaN(parseFloat(myPayment))) {
      var P = this.principal;
      var i = this.decimalInterest;
      var n = this.years;
      var q = this.interval ;
      
      var payment = parseFloat("0.0");
      var M = payment;
      
      M = (P * i) / (q * (1 - Math.pow(( 1 + ( i / q ) ), -((n * 12)))));
      this.monthlyPayment = M;
    } else {
      this.monthlyPayment = myPayment;
    }
      
      return this.monthlyPayment;
  }
}

function amortizer_setMonthlyPayment(myPayment) {
  if (!isNaN(parseFloat(myPayment))) {
    this.monthlyPayment = myPayment;
  } else {
    alert("Could not set Monthly Payment to value: " + myPayment);
    this.getMonthlyPayment();
  }
}

function amortizer_getBalance() {
  if (this.valid) {

    var M = this.monthlyPayment;
    var n = this.years;
    var q = this.interval;
    
    if (M == 0) {
      M = this.getMonthlyPayment();
    }
    
    this.balance = (M * n * q);
    return this.balance;
  }
}

function amortizer_getInterestBalance(term) {
  if (this.valid) {
    var P = this.principal;
    var M = this.monthlyPayment;
    var n = this.years;
    if (term ) n = term;
    var q = this.interval;
   
    if (M == 0) {
      M = this.getMonthlyPayment();
    }
 
    if (this.totalInterestPaid == 0 ) {
      this.interestBalance = ((M * n * q) - P);
      return this.interestBalance;
    } else {
      return this.totalInterestPaid;
    }
  }
}

function amortizer_getInterestOnlyMonthlyPayment() {
 
  if (this.valid) {
    var P = this.principal;
    //var M = this.monthlyPayment;
    var i = this.getDecimalInterest();
    //  var n = this.years;
    var q = this.interval;
    this.interestOnlyMonthlyPayment =  ((P * i) / q);
    return this.interestOnlyMonthlyPayment;
  }
 
}

function amortizer_setTermYears(years) {

  if (!isNaN(parseFloat(years)) && (years > 0)) {
    this.years = years;
  } else {
    alert("Please enter a valid Term, in years.");
  }
}

function amortizer_getRemainingPrincipal(paymentNumber,myMonthlyPayment) {
  //  alert ("I think my monthly payment is :" + myMonthlyPayment);
  var k = paymentNumber;
  var P = this.getPrincipal();
  var q = this.getInterval();
  var M = (!isNaN(parseFloat(myMonthlyPayment))) ? myMonthlyPayment  : this.getMonthlyPayment();
  var i = this.getDecimalInterest();
  //alert ("I think my monthly payment is :" + M);
  //  if (this.schedule.getLength() < (k - 1 )) {
  this.setSchedule(k,M);
    //  }
  
  // alert("my nominal A is : " + ((P-M*q/i) * Math.pow((1 + i / q),k) + (M * q / i) ) ) ;
  
  for (var j = 0; j < this.schedule.getLength();j++ ) {
    P -= this.schedule.getElementAt(j).getPrincipal();
  }    
  // alert ("my computed A is : "  + P) ;
  return P;

}

function amortizer_getPrincipalPaidThisPayment(payment) {

  var k= payment;
  if (this.schedule.getLength() == 0 ) {
    this.setSchedule();
  }
  return this.schedule.getElementAt(k-1).getPrincipal();
}

function amortizer_getInterestPaidThisPayment(payment) {
  var k= payment;
  if (this.schedule.getLength() == 0 ) {
    this.setSchedule();
  }
  return this.schedule.getElementAt(k-1).getInterest();
}

function amortizer_setSchedule(payment,myMonthlyPayment) {
  var DEBUG = false;
  if (document.debug) DEBUG = true; 
  var currentPrincipalPayment = 0;
  var currentInterestPayment = this.getInterestOnlyMonthlyPayment();
  var paid = undefined;
  var totPPayed = 0;
  var M = (!isNaN(parseFloat(myMonthlyPayment))) ? myMonthlyPayment  : this.getMonthlyPayment();
  var P = this.getPrincipal();
  var q = this.interval;
  var k = ((payment == undefined) ? (12 * this.getTermYears()) : payment);
  var i = this.getDecimalInterest();
  this.schedule.clear();

  for (var j = 1; j <= k ; j++) { //remember that the real k is i+1!
   
    currentPrincipalPayment = M - currentInterestPayment ;
    totPPayed += currentPrincipalPayment;
    this.totalInterestPaid += currentInterestPayment;
    if(DEBUG) {
      STDERR += j  + " Bal: " + setScale(P,2) + " PriPmt: "+ setScale(currentPrincipalPayment,2) + " IntPmt: " + 
	setScale(currentInterestPayment,6) + "= " + setScale((setScale(currentPrincipalPayment,2) + setScale(currentInterestPayment,2)),2) + 
	" M: " + setScale(M,2) + "\n";  
    }
    if (currentPrincipalPayment <= P) { 
      paid = new Payment(currentPrincipalPayment,currentInterestPayment);
      this.schedule.add(paid);
    } else {
      paid = new Payment(P,currentInterestPayment);
      this.schedule.add(paid);
      break;
    }
      
    if(this.ach & (j == 1)) { i -= .25/100 }
    if(this.onePercentOff & (j == this.onePercentOffStart)) { i -= (1/100)}
  
    currentInterestPayment =  (( P -= currentPrincipalPayment) * i / q); 
  } 
 
  if(DEBUG) STDERR += (totPPayed + this.totalInterestPaid) + " : " + totPPayed + " : " + this.totalInterestPaid +"\n";
  if(DEBUG) document.debug.out.value = STDERR;
}

function amortizer_getSchedule() {

  if (this.schedule.getLength() == 0 ) {
    this.setSchedule();
  }
  return this.schedule;

}

function amortizer_getRemainingAmortizer(payment, interest) {
 
  var newInt = this.getInterest;
  if (interest) {
    newInt = interest;
  }

  var remainingAmortizer = new amortizer(this.getRemainingPrincipal(payment), this.getInterest(), (this.getTermYears() - (payment / 12)));
  
  return remainingAmortizer;

}

