var PaymentCalculator = Class.create({
  initialize: function(params) {
    this._errors = {
      paymentsRequired:  'The Number of Payments field is required.',
      paymentsFormat:    'The Number of Payments field must be an integer between 1 and 480.',
      interestRequired:  'The Interest Rate field is required.',
      interestFormat:    'The Interest Rate field must be a number between 1 and 99.',
      principalRequired: 'The Principal field is required.',
      principalFormat:   'The Principal field must be an integer between 100 and 10000000.'
    };
    this._payments  = $(params.payments)  || null;
    this._interest  = $(params.interest)  || null;
    this._principal = $(params.principal) || null;
    this._total     = $(params.total)     || null;
    this._msgs      = $(params.messages)  || null;
    this._calc      = $(params.calculate) || null;
    this._init();
  },
  _init: function() {
    this._calc.observe('click', this._calculate.bindAsEventListener(this));
    this._payments.observe('keypress',
      this._preventDollarCommaPercentChars.bindAsEventListener(this._payments));
    this._interest.observe('keypress',
      this._preventDollarCommaPercentChars.bindAsEventListener(this._interest));
    this._principal.observe('keypress',
      this._preventDollarCommaPercentChars.bindAsEventListener(this._principal));
  },
  _calculate: function(evt) {
    evt.stop(); // Stop event immediately

    var msg       = '';
    var payments  = $F(this._payments);
    var interest  = $F(this._interest);
    var principal = $F(this._principal);
    if (payments.blank()) {
      msg = this._errors.paymentsRequired;
    } else if (interest.blank()) {
      msg = this._errors.interestRequired;
    } else if (principal.blank()) {
      msg = this._errors.principalRequired;
    }
    if (!msg.blank()) {
      this._msgs.update('<p class="error">' + msg + '</p>');
      this._total.update('$0.00');
      return false;
    }
    payments  = parseInt(payments);
    interest  = parseFloat(interest);
    principal = parseInt(principal);
    if (isNaN(payments) || (payments < 1 || payments > 480)) {
      msg = this._errors.paymentsFormat;
    } else if (isNaN(interest) || (interest < 1 || interest > 99)) {
      msg = this._errors.interestFormat;
    } else if (isNaN(principal) || (principal < 100 || principal > 10000000)) {
      msg = this._errors.principalFormat;
    }
    if (!msg.blank()) {
      this._msgs.update('<p class="error">' + msg + '</p>');
      this._total.update('$0.00');
      return false;
    }
    var interestVal = interest / 100;
    interestVal /= 12;
    var power = 1;
    for (var i = 0; i < payments; i++) {
      power *= (1 + interestVal);
    }
    var total = (principal * power * interestVal) / (power - 1);
    this._msgs.update('&nbsp;');
    this._total.update('$' + total.toFixed(2));

    return false;
  },
  _preventDollarCommaPercentChars: function(evt) {
    var pressed = (window.event) ? window.event.keyCode : evt.which;
    if (pressed == 36 || pressed == 37 || pressed == 44) {
      // 36 => $ (dollar-sign) 37 => % (percent) 44 => , (comma)
      evt.stop();
      return false;
    }
    return true;
  }
});
document.observe('dom:loaded', function() {
  new PaymentCalculator({
    payments:  'payments',
    interest:  'interest',
    principal: 'principal',
    total:     'total',
    messages:  'messages',
    calculate: 'calc'
  });
});