var Validation = new Class({
  currentForm: false,
  keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  validationData: false,

  initialize: function()
  {
    this.initializeForms();
  },

  initializeForms: function()
  {
    var forms = document.forms;

    for (var i = 0; i < forms.length; i++) {
      if (typeof forms[i].elements.validationData != "object") continue;
      this.currentForm = forms[i];
      this.initializeForm(forms[i]);
    }
  },

  initializeForm: function( form )
  {
    var me = this;
    this.validationData = Json.evaluate(this.uudecode(form.elements.validationData.value)).validationData;
    for (var i = 0; i < this.validationData.length; i++) {
      var name = this.validationData[i].name;

      var elements = $(form).getElements("input[name^="+name+"]");
      if (typeof elements != "object" || elements.length <= 0) 
        elements = $(form).getElements("select[name^="+name+"]");
      if (typeof elements != "object" || elements.length <= 0) 
        elements = $(form).getElements("textarea[name^="+name+"]");
      if (typeof elements != "object" || elements.length <= 0) continue;

      for (var j = 0; j < elements.length; j++) {
        var element = $(elements[j]);
        var event = this.validationData[i].event;

        if (element.validateEvents >= 1) {
          element.validateEvents++;
        } else {
          element.validateEvents = 1;
          element.removeEvents();
          element.validating = 0;
        }
         
        element.validationDataIndex = i;
        eval("var validateFunction = function() { me.validateField(this,"+i+"); }");
        element.addEvent(event, validateFunction );

        element.addEvent("focus", this.showErrorMessage.bindWithEvent(this) );
        element.addEvent("blur", this.hideErrorMessage.bindWithEvent(this) );

        if (this.validationData[i].error && !element.serverError) {
          element.serverError = true;
          this.validateField(element, i);
        }
      }
    }
  },

  validateField: function( element, validationDataIndex )
  {
    element.validating++;

    var field = this.validationData[validationDataIndex];
    var result = true;
    switch (field.type) {
      case "required":
        if (element.value == "") result = false;
      break;
      case "checked":
        if (!element.checked) result = false;
      break;
      case "email":
        var objRE = /^[0-9a-zA-Z]([-_.]*[0-9a-zA-Z])*@[0-9a-zA-Z]([-.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,6}$/;
        if (element.value == "") break;

        result = (objRE.test(element.value));
      break;
      case "number":
        if (isNaN(element.value)) result = false;
      break;
      /*
      case "date":
        var objRE = /^[0-9]{2}\-[0-9]{2}\-[0-9]{4}$/;
        if (element.value == "") break;
        result = (objRE.test(element.value));
      break;
      */
      case "phone":
        var objRE = /^[0-9()\-\ \+]{8,}$/;
        if (element.value == "") break;
        result = (objRE.test(element.value));
      break;
      case "equal":
        var otherElementName = field.argument[0];
        if (typeof otherElementName != "string" || otherElementName == "") break;
        var otherElement = this.currentForm.elements[otherElementName];
        if (typeof otherElement != "object") break;
        if (otherElement.value != element.value) result = false;
      break;
      case "date":
      case "time":
      case "unique":
        if (field.error) {
          result = false;
          field.error = false;
        } else {
          result = true;
        }
      break;
    }

    if (!result) {
      element.errorMessage = field.message;
      element.error = true;
      this.showError(element);
    } else if (!element.error) {
      this.hideError(element);
    }

    if (element.validating >= element.validateEvents) {
      element.validating = 0;
      element.error = false;
    }
    return result;
  },

  showError: function (element)
  {
    element.addClass("validationError");
    if (element.id && element.id.indexOf("[") < 0) {
      var label = document.getElement("label[for="+element.id+"]");
      if (label) label.addClass("validationError");
    }
  },

  hideError: function (element)
  {
    element.removeClass("validationError");
    if (element.id && element.id.indexOf("[") < 0) {
      var label = document.getElement("label[for="+element.id+"]");
      if (label) label.removeClass("validationError");
    }
  },

  showErrorMessage: function (e)
  {
    var element = e.target;
    if (!element.hasClass("validationError")) return;

    var coordinates = $(element).getCoordinates();
    var message = new Element("div", {
      "class": "validationErrorMessage",
      "styles": {
        "position": "absolute",
        "top": coordinates.top + "px",
        "left": coordinates.left + coordinates.width + "px"
      },
      "id": "validationErrorMessage_"+element.id
    });
    message.innerHTML = element.errorMessage;
    document.body.appendChild(message);
//    message.injectAfter(element);
  },

  hideErrorMessage: function (e)
  {
    var element = e.target;
    if ($("validationErrorMessage_"+element.id)) {
      $("validationErrorMessage_"+element.id).remove();
    }
  },

  uudecode : function (input)
  {
    var output = "";
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    do {
      enc1 = this.keyStr.indexOf(input.charAt(i++));
      enc2 = this.keyStr.indexOf(input.charAt(i++));
      enc3 = this.keyStr.indexOf(input.charAt(i++));
      enc4 = this.keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }
    } while (i < input.length);

    if (typeof(String.prototype.utf8decode) !== "undefined") {
      return output.utf8decode();
    } else {
      return output;
    }
  }
});

var validation;
window.addEvent("domready", function() { validation = new Validation(); } );

