if (Form == undefined) var Form = { };

Form.Validator = function(form) {
  if (!form) {
    throw('A valid form was not passed in.');
  }
  this.form  = form;
  this.list  = [ ];
  this.stash = { };
};

Form.Validator.prototype = {

  form: null,
  list: null,
  report: null,
  stash: null,

  set: function(field, constraint, option) {
    if (!this.form[field]) {
      throw(field + " is not a valid form input");
    }

    var c = { };

    if (typeof(option) == 'string') {
      c.onFailure = option;
    } else {
      c = option;
    }

    if (typeof(constraint) == 'string') {
      c.constraint = this[constraint];
    } else {
      c.constraint = constraint;
    }

    c.field = field;
    this.list.push(c);
  },


  get: function(field) {
    var constraints = new Array();
    for (i in this.list) {
      var c = this.list[i];
      if (c.field == field || field == null) {
        constraints.push(c);
      }
    }
    return constraints;
  },


  reporter: function() {
    if (arguments.length == 0) {
      if (this.report == null) {
        this.report = new Form.Validator.Report.AlertAll(this);
      }
    } else {
      if (typeof(arguments[0]) == 'string') {
        var proto   = 'Form.Validator.Report.' + arguments[0];
        var code    = 'new ' + proto + '(this);';
        this.report = eval(code);
      } else {
        this.report = arguments[0];
      }
    }
    return this.report;
  },


  validate: function() {
    var i, j, c;
    var errors   = 0;
    var reporter = this.reporter();
    var constraints;

    if (arguments.length == 0) {
      constraints = this.list;
    } else {
      constraints = [ ];
      for (i = 0; i < arguments.length; i++) {
        var field = arguments[i];
        var clist = this.get(field);
        for (j = 0; j < clist.length; j++) {
          constraints.push(clist[j]);
        }
      }
    }

    reporter.start(constraints);
    try {
      var ok;
      for (i = 0; i < constraints.length; i++) {
        c  = constraints[i];
        ok = c.constraint(this, c.field);
        if (!ok) { errors++ }
        reporter.run(ok, c);
      }
    }
    catch (e) {
    }
    reporter.finish();

    if (errors > 0) {
      return false;
    } else {
      return true;
    }
  },


  // VALIDATION FUNCTIONS
  notBlank: function(self, field) {
    var blankness = new RegExp(/^\s*$/);
    var f = self.form[field];
    if (f.value == '' || blankness.test(f.value)) {
      return false;
    } else {
      return true;
    }
  },
  
  isEmail: function(self, field) {
    var isemail = new RegExp(/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/);
    var f = self.form[field];
    if (isemail.test(f.value)) {
      return true;
    } else {
      return false;
    }
  }

};