/**
 * YAHOO.applegate.validation
 * Only provides methods to apply messages from a BindingResult (spring form post) to a form.
 */
(function(){
  YAHOO.namespace("applegate.validation");

  var Dom = YAHOO.util.Dom,
      Selector = YAHOO.util.Selector,
      Tooltip = YAHOO.widget.Tooltip,
      global = YAHOO.applegate.global,
      validation = YAHOO.applegate.validation;

  //noinspection JSUnusedLocalSymbols
  var exampleBindingResult = {
    hasErrors:true,
    fieldErrors:[
       {objectName:"model", message:"Empty subject line", field:"emailDescriptor.subject",bindingFailure:false,rejectedValue:""},
       {objectName:"model", message:"There are no recipents", field:"emailDescriptor.toEmailAddresses", bindingFailure:false, "rejectedValue":[]}
    ]
  };

  function createMessage(text){
    var message = document.createElement("div");
    message.className = 'message';
    message.innerHTML = text;
    return message;
  }

  validation.applyBindingResultToForm = function( bindingResult, form){
    validation.clearMessages(form);
    var elMessages = validation.locateMessagesElement(form);
    if( bindingResult.hasErrors ){
      // global first
      if( bindingResult.globalErrors ){
        global.forEach(bindingResult.globalErrors, function(error){
          elMessages.appendChild(createMessage(error.message));
        });
      }
      // then field errors
      if( bindingResult.fieldErrors ){
        global.forEach(bindingResult.fieldErrors, function(error){
          var elements = validation.locateErrorElements(form, error);
          global.forEach(elements, function(element){
            Dom.addClass(element,"applegate-validation-error");
            var tt = element.applegateValidationErrorTooltip ;
            if( typeof tt == "undefined"){
              tt =  new Tooltip(Dom.generateId() , {
                context:element,
                container:form
              });
              element.applegateValidationErrorTooltip = tt ;
            }
            tt.cfg.setProperty("text", error.message);
            tt.cfg.setProperty("disabled", false);
          });
          elMessages.appendChild(createMessage(error.message));
        });
        // adjust the form focus
        var firstError = Selector.query('input.applegate-validation-error', form, true);
        if( firstError ) firstError.focus() ;
      }
    }
  };

  validation.clearMessages = function( form ){
    var currentErrors = Selector.query(".applegate-validation-error", form);
    global.forEach(currentErrors, function(element){
      element.applegateValidationErrorTooltip.cfg.setProperty("disabled", true);
      Dom.removeClass(element, 'applegate-validation-error');
    });
    validation.locateMessagesElement(form).innerHTML='';
  };

  validation.locateErrorElements = function(form, error){
    var field = form[error.field] ;
    if( !field ){
      field = form[error.field +"_edit"];
    }
    var fields ;
    // watch form.fieldName returning a NodeList
    if(typeof field.length === "number"){
      fields = global.toArray(field);
      field = fields[0];
    }else{
      fields = [field];
    }
    // field is an input and is used as an example of the reset of the inputs

    // now must locate a suitable element to hang the validation from
    var container = field ;
    if( field.type === "hidden" || Dom.hasClass(field, "edit") || Dom.hasClass(field, "yui-ac-input") ){
      container = global.up(field, '.applegate-validation-container') || container;
    }
    // attempt to locate the label for the element
    if( field.id ){
      var label = Selector.query("label[for="+ field.id+"]",form, true);
      return label ? [container,label] : [container];
    }
    return [container];
  };

  validation.locateMessagesElement = function(form){
    var el = Selector.query('.applegate-validation-messages', form, true);
    if( !el ){
      el = document.createElement("div");
      Dom.addClass(el, "applegate-validation-messages");
      form.insertBefore(el,form.firstChild);
    }
    return el ;
  };
})();