// This file depends on:
//
//jquery-1.4.2.min
//jquery.validate.min.js
//jquery.scrollTo-min.js

var FORMS = function(){
  
  var FORM_DEBUG = false;

  function hideHiddenFieldsInForm(form){
    $(form).find("input").each(function(){
      if( $(this).attr("type") == "hidden" ){
        $(this).attr("name",$(this).attr("name") + "-ignore")
      }
    })
  }

  function unhideHiddenFieldsInForm(form){
    $(form).find("input").each(function(){
      if( $(this).attr("type") == "hidden" ){
        $(this).attr("name", $(this).attr("name").substring(0, $(this).attr("name").lastIndexOf("-ignore")))
      }
    })
  }
  
  function getFieldValue(element){
    var elementValue = null
    if($(element).val != null){
      elementValue = $(element).val()
    }else if($(element).text != null){
      elementValue = $(element).text()
    }

    if(elementValue == ""){
      elementValue = null;
    }

    return elementValue;
  }
  
  function hasExceedWordMax(element,word_count){

    var elementValue = getFieldValue(element);

    if(elementValue != null){
      var words = elementValue.replace(/\s/g,' ').split(' ');
      var count = 0;
      for(var i = 0; i < words.length; i++){
        if( words[i].length > 0 ){
          count ++;
        }
      }

      if(count > word_count){
        return true;
      }else{
        return false;
      }
    }
  }
  
  function isForm( form ){
    if( form == null || form.length !== 1 || !$(form).is('form') ){
      return false;
    }else{
      return true;
    }
  }
  
  function placeErrorInForm( form, errorMsg ){

    if( !isForm( form ) ){
      if( FORM_DEBUG ){
        window.alert("placeErrorInForm: given element is not a form.");
      }
      return;
    }

    if( errorMsg == null || typeof(errorMsg) !== 'string' ){
      if( FORM_DEBUG ){
        window.alert("placeErrorInForm: given error message is not a string.");
      }
      return;
    }
    
    $(form).find("#errorExplanation").remove();
    $(form).prepend("<div id='errorExplanation' class='errorExplanation'> <h2></h2> <p></p> </div>");
    var errorTitle = $(form).find("#errorExplanation h2");
    var errorText = $(form).find("#errorExplanation p");
    $(errorTitle).text("ERROR");
    $(errorText).text(errorMsg);
    
    //Scroll to the error message
    $.scrollTo( $(errorTitle) );
  }

  /**
   * Sets up validation for a given form using the given rules which display the given error messages if
   * they are not satisfied. An optional callback function may be provided that is executed when an arror occurs.
   * This callback recieves a string that is the error message for the first unsatisfied condition.
   *
   * @param form : The form element.
   * @param rules : The set of rules. See JQuery Validation plugin documentation for details. In addition to the 
   * JQuery Validation rules, this validator will also accept 'maxWords' property. The 'max' property will be ignored
   * if 'maxWords' is specified.
   * @param errorMsgs : The set of error message. See JQuery Validation plugin documentation for details.
   * @param callbk : An optional callback that is executed if the form fails to validate.
   */
  function validateForm( form, rules, errorMsgs, callbk ){
    
    if( !isForm( form ) ){
      if( FORM_DEBUG ){
        window.alert("validateForm: given element is not a form.");
      }
      return;
    }
    
    if( rules == null || typeof(rules) !== 'object'){
      if( FORM_DEBUG ){
        window.alert("validateForm: no rules object provided.");
      }
      return;
    }
    
    if( errorMsgs == null || typeof(errorMsgs) !== 'object'){
      if( FORM_DEBUG ){
        window.alert("validateForm: no error message object provided.");
      }
      return;
    }
    
    //Parse rules
    for ( element in rules ) {
      for( rule in rules[element] ){
        
        //Add hack to enforce word counts
        if( rule == 'maxWords'){
          var maxWords = rules[element][rule];
          rules[element]['max'] = {
            depends: function( e ){
              if( hasExceedWordMax( e, maxWords ) ){
                return -1;
              }else{
                return false;
              }
            }
          };
          rules[element][rule] = undefined;
        }
        
      }
    }
    
    //Parse error messages
    for ( element in errorMsgs ){
      for( msg in errorMsgs[element] ){
        
        if( msg == 'maxWords'){
          var maxWordsMsg = errorMsgs[element][msg];
          errorMsgs[element]['max'] = maxWordsMsg;
          errorMsgs[element][msg] = undefined;
        }
        
      }
    }
    
    var errorOccurred = false;
    var errorMessage = "";
    
    hideHiddenFieldsInForm( form );

    $(form).validate({
      
      submitHandler: function(f) {
        unhideHiddenFieldsInForm( f );
        f.submit();
      },
      
      focusInvalid: false,
      onfocusout: false,
      onkeyup: false,
      onclick: false,
      errorClass: "invalidField",
      
      rules: rules,
      messages: errorMsgs,
      
      invalidHandler: function() {
        errorOccurred = false;
      },

      errorPlacement: function(error, element) {
        // Only capture the first error
        if( !errorOccurred ){
          errorOccurred = true;
          errorMessage = $(error).text();
          placeErrorInForm( form, errorMessage );
          if( callbk !== null && typeof(callbk) == 'function' ){
            callbk( errorMessage );
          }
        }
      }
      
    });

  }

  return { validateForm:validateForm };

}();
