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.VERSION = '0.31';

// Form.Validator Class
Form.Validator.prototype = {

  // form that this object is validating
  form: null,

  // list of constraints
  list: null,

  // when validation fails, this is how you report your failure.
  report: null,

  // temporary storage for inter-object communication
  stash: null,

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

    var c = { };

    if (typeof(option) == 'string') {
      // onFailure message (for backwards compatibility)
      c.onFailure = option;
    } else {
      // assume it's an object w/ sane values
      c = option;
    }

    if (typeof(constraint) == 'string') {
      // predefined validator
      c.constraint = this[constraint];
    } else {
      // function reference w/ a custom validator
      c.constraint = constraint;
    }

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

  // get constraint info for a field. 
  // (this can return more than 1 constraint)
  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;
  },

  // define how validation failures are handled
  reporter: function() {
    if (arguments.length == 0) {
      if (this.report == null) {
        // this is the default action
        this.report = new Form.Validator.Report.AlertAll(this);
      }
    } else {
      if (typeof(arguments[0]) == 'string') {
        // instantiate one of our built-in reports
        var proto   = 'Form.Validator.Report.' + arguments[0];
        var code    = 'new ' + proto + '(this);';
        this.report = eval(code);
      } else {
        // assume they gave as a validation action
        // object that can start(), run() and finish().
        this.report = arguments[0];
      }
    }
    return this.report;
  },

  // run validation tests
  // 0 params means run all the tests
  // 1 or more params means run the tests for the fields specified
  validate: function() {
    var i, j, c;
    var errors   = 0;
    var reporter = this.reporter();
    var constraints;

    // figure out what we have to validate and populate constraints array
    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]);
        }
      }
    }

    // actual validation begins here, iterating through constraints
    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++ }
        res= reporter.run(ok, c);
        if (res) {
          this.form[c.field].style.backgroundColor= '#b7e1ac';
        }
        else {
          this.form[c.field].style.backgroundColor= 'red';
        }
      }
    }
    catch (e) {
      // alert(e);
    }
    reporter.finish();

    // if anything went wrong, return false
    if (errors > 0) {
      return false;
    } else {
      return true;
    }
  },

  // XXX - This is going to become Form.Validator.Report.AlertAll
  // This displays an alert box telling you what went wrong.
  /*
  validateAndAlert: function() {
    var messages = this.validate();
    if (messages.length > 0) {
      alert(messages.join("\n"));
      return false;
    }
  },
  */

  // for backwards compatibility, we provide this,
  // but DON'T USE IT FOR NEW CODE.
  validateAndAlert: function() {
    var save = this.reporter();
    this.reporter('AlertAll');
    var result = this.validate(arguments);
    this.reporter(save);
    return result;
  },

  // VALIDATION FUNCTIONS

  // false is bad
  // true  is good

  // Make sure a field's value is not blank
  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;
    }
  },
  // ...meaning, you can't be Blank; if you are, you messed up;
 
  // Make sure a field's value is not 0
  notZero: function(self, field) {
    if (self.form[field].value == "0") {
      return false;
    } else {
      return true;
    }
  },

  // METHODS THAT GENERATE VALIDATION CLOSURES
  makeOptional: function(f) {
    return function(fv, field) {
      if (fv.notBlank(fv, field)) {
        return f(fv, field);
      } else {
        return true;
      }
    }
  },

  // Make sure field is at least n characters long
  makeLengthMin: function(n) {
    return function(fv, field) {
      if (fv.form[field].value.length < n) {
        return false;
      } else {
        return true;
      }
    }
  },

  // Make sure field is not more than n characters long
  makeLengthMax: function(n) {
    return function(fv, field) {
      if (fv.form[field].value.length > n) {
        return false;
      } else {
        return true;
      }
    }
  },

  // Make sure field is at least n (or greater)
  makeValueMin: function(n) {
    return function(fv, field) {
      if (fv.form[field].value < n) {
        return false;
      } else {
        return true;
      }
    }
  },

  // Make sure field is at most n (or less).
  makeValueMax: function(n) {
    return function(fv, field) {
      if (fv.form[field].value > n) {
        return false;
      } else {
        return true;
      }
    }
  },

  // Make sure a field matches the given regex
  makeMatchRegex: function(regex) {
    return function(fv, field) {
      return regex.test(fv.form[field].value);
    }
  },

  // Make sure a field does not match the given regex
  makeNotMatchRegex: function(regex) {
    return function(fv, field) {
      return !regex.test(fv.form[field].value);
    }
  },
// --> START -  Aggiunto da Mac
  // Make sure field is at most n (or less).
  compareWith: function(field1) {
    return function(fv, field) {
      if (fv.form[field].value != fv.form[field1].value) {
        return false;
      } else {
        return true;
      }
    }
  }
// <-- END
};

