/********************************************************************************************
 *
 *		  TITLE:  AbleEngine Plugin - Simple Form Validation
 *   MODIFIED:	2011.09.20
 *		 AUTHOR: 	Graham Wheeler
 *	 REQUIRES:	AE Core 2.1.1
 *
 ********************************************************************************************/

(function($){

  AE.Validator = {
    
    validationPatterns: [
      
      { name: "pattern-email", pattern: /^([0-9a-zA-Z]+([_.-]?[0-9a-zA-Z]+)*@[0-9a-zA-Z]+[0-9,a-z,A-Z,.,-]*(.){1}[a-zA-Z]{2,4})+$/, error: "Email address not in valid format" },
      { name: "pattern-phone-fax", pattern: /^(1\s*[-\/\.]?)?(\((\d{3})\)|(\d{3}))\s*[-\/\.]?\s*(\d{3})\s*[-\/\.]?\s*(\d{4})\s*(([xX]|[eE][xX][tT])\.?\s*(\d+))*$/, error: "Number not in valid format" },
      { name: "pattern-positive-number", pattern: /^[1-9]+([0-9])*$/, error: "Must be a number greater than zero" }
      
    ],
    
    getLabel: function(el) {

      if (el.title != "") {
        return "'"+el.title+"'";
      } else {
        return "'"+el.name+"'";
      }				
      
    },
    
    isValid: function(el) {

      try {
	      var errors = [];
	      
	      var self = this;
	      
	      this.container = el;
	      this.$c = $(el);
	    
	      // 
	      //	Set to "alert" to have errors displayed in a javascript alert window, or
	      //	"inline" to have them appear next to the referenced form fields
	      //
	      this.notificationMethod = (this.$c.attr("notificationmethod") != undefined) ? this.$c.attr("notificationmethod") : "inline";
	      
	      // 
	      //	Set to "before" or "after" to set the position of inline error messages
	      //	relative to the referenced form field
	      //
	      this.notificationPosition = (this.$c.attr("notificationposition") != undefined) ? this.$c.attr("notificationposition") : "after";
	
	
	      //
	      //	Verify that the input is not empty
	      //
	      $(".required:visible", this.container).each( function() {
	        if ($(this).val() == "" && !$(this).hasClass("match-pattern")) {
	          var el = this;
	          errors.push({ 
	            field: el,
	            message: $(el).attr('data-requirederror') || "Must be provided"
	          });
	        }
	      });
	      
	      
	      //
	      //	Compares two values to verify that they are the same
	      //
	      $("[crosscheck]:visible", this.container).each( function() {
	        if ($(this).val() != $($(this).attr("crosscheck") ).val()) {
	          var el = this;
	          errors.push({ 
	            field: el,
	            message: $(el).attr('data-matcherror') || "Values do not match"
	          });
	        }
	      });
	
	      
	      //
	      //	Verify that the input value conforms to certain patterns
	      //
	      $(".match-pattern:visible", this.container).each( function() {
	        if (($(this).hasClass("required") && this.value == "" ) || this.value != "") {
	
	          for (var i = 0; i < self.validationPatterns.length; i++) {
	            
	            var p = self.validationPatterns[i];
	            if ($(this).hasClass( p.name ) && !p.pattern.test(this.value)) {
	              var el = this;
	              errors.push({ 
	                field: el,
	                message: p.error
	              });
	            }	
	          }
	
	        }
	      });		
	      
	      //
	      //	Verify that the selected value of a select box is NOT an invalid option
	      //
	      $("select.check-for-valid-selection:visible", this.container).each( function() {
	        var opt = this.options[this.selectedIndex];
	        if ($(opt).hasClass("InvalidSelection")) {
	          var el = this;
	          errors.push({ 
	            field: el,
	            message: $(el).attr('data-invalidoptionerror') || "Invalid option"
	          });
	        }
	      });
	
	      //
	      //	Verify that at least one member in a set of checkboxes or radio buttons is selected
	      //
	      $(".must-select-one:visible", this.container).each( function() {																														 
	        var hasAtLeastOneSelectedValue = ($("input:checked", this).length > 0);
	        var hasAtLeastOneUserDefinedValue = ($('input[type="text"], textarea', this).filter(function(){
	          return ($(this).val().length > 0);
	        }).length > 0);
	        if (!hasAtLeastOneSelectedValue && !hasAtLeastOneUserDefinedValue) {
	          var el = this;
	          errors.push({ 
	            field: el,
	            message: $(el).attr('data-noneselectederror') || "Must select at least one value"
	          });
	        }
	      });		
	
	      if (errors.length > 0) {
	        
	        if (this.notificationMethod == "alert") {
	          
	          var eList = "Please correct the following errors:\n\n";
	          
	          for (var i = 0; i < errors.length; i++) {
	            eList += getLabel(errors[i].field) + ": " + errors[i].message + "\n";
	          }
	
	          alert(eList.toString());
	
	        } else if (this.notificationMethod == "inline") {
	
	          // remove previous error messages if any exist
	          $(".validation-error-message, .validation-error-summary", this.container).remove();
	          $(".failed-validation", this.container).removeClass("failed-validation");
	          
	          for (var i = 0; i < errors.length; i++) {
	            
	            var field = $( errors[i].field );
	            $(field).addClass("failed-validation");
	
	            var message = '<span class="validation-error-message">'+errors[i].message+'</span>';
	            if ( this.notificationPosition == "before" ) { field.before(message); }
	            else if ( this.notificationPosition == "after" ) { field.after(message); }
	
	          }
	          
	          if (errors.length > 0) {
	            $(this.container).append('<div class="validation-error-summary">Please review the form and correct any errors for highlighted field(s)!</div>');
	          }
	          
	        }
	        
	        return false;
	        
	      } else {
	      
	        return true;
	        
	      }    	  
      } catch (ex) {
    	  return false;
      }

    }
    
  };


  $(function() {

    $(document).bind("click", function(e) {
      var type = $(e.target).attr("type");
      if ( type == "submit" || type == "image" ) {
        if (AE.Validator.isValid($(e.target).closest("form.validated"))) {
          return true;
        } else {
          e.preventDefault();          
          return false;
        }
      } else {
        return;
      }
    });
    
    $('input.failed-validation, textarea.failed-validation').live("keydown, click", function(e) {
      var t = $(e.target);
      t.removeClass("failed-validation");
      t.next(".validation-error-message").remove();
      t.prev(".validation-error-message").remove();
    });    
    
    $('.must-select-one.failed-validation').live("click", function(e) {
      var t = $(e.target).closest('.must-select-one');
      t.removeClass("failed-validation");
      t.next(".validation-error-message").remove();
      t.prev(".validation-error-message").remove();
    });

  });

})(AE.select);
