/**
 * @author Dale Larsen for Fabuso LLC
 * detect if input data is valid
 */
(function($){
   //TODO: make this object able to receive more than one input. use an array for options.input, same with errorMsg, etc.
   $.fn.validateInput = function(options){
   
      var defaults = {
         noName: 'Enter Site Name Here',
         redir: false,
         redirTitle: false,
         input: '#inputName',
         errorDiv: '#errorDiv',
         errorMsg: 'Please enter a valid name.',
         onType: false,
         isEmail: false,
         isPhone: false,
         useDefaultOnType: false,
         setNextStep: false,
         toggleType: 'fade',
         customValid: 'none',
         msgFadeOut: true,
         success: false//this is a success callback that you may call, make sure redir is false
      };
      var options = $.extend(defaults, options);
      
      return this.each(function(){
      
         var obj = $(this);
         var objInput = $(options.input);
         if (options.noName) {
            objInput.inputTextGhost({
               text: options.noName
            });
         } else {
            objInput.inputTextGhost({
               text: objInput.val()
            });
         }
         
         if (options.onType) {
            var onTypeInterval;
            objInput.keypress(function(){
               clearTimeout(onTypeInterval);
               onTypeInterval = setTimeout(function(){
               
                  if (options.onType != true) {
                     options.onType.call(this);
                  }
                  
                  if (options.useDefaultOnType) {
                  
                     var enteredName = objInput.val();
                     
                     if ((enteredName == '') || (!enteredName) || (enteredName == options.noName)) {
                     
                        if (options.toggleType == 'fade') {
                           obj.fadeOut(500);
                        } else if (options.toggleType == 'hide') {
                           obj.hide(500);
                        } else {
                           obj.fadeOut(500);
                        }
                        
                     } else {
                     
                        if (options.toggleType == 'fade') {
                           obj.fadeIn(500);
                        } else if (options.toggleType == 'hide') {
                           obj.show(500);
                        } else {
                           obj.fadeIn(500);
                        }
                     }
                  }
                  
               });
               
            });
         }
         
         obj.click(function(){
            _validateInput({
               noName: options.noName,
               obj: obj,
               redir: options.redir,
               redirTitle: options.redirTitle,
               input: objInput,
               errorDiv: options.errorDiv,
               errorMsg: options.errorMsg,
               onType: options.onType,
               isEmail: options.isEmail,
               isPhone: options.isPhone,
               useDefaultOnType: options.useDefaultOnType,
               setNextStep: options.setNextStep,
               toggleType: options.toggleType,
               customValid: options.customValid,
               msgFadeOut: options.msgFadeOut,
               success: options.success
            });
         });
         
      });
   };
   
})(jQuery);

function _validateInput(options){

   var defaults = {
      noName: 'Enter Site Name Here',
      obj: false,
      redir: false,
      redirTitle: false,
      input: '$(#inputName)',
      errorDiv: '#errorDiv',
      errorMsg: 'Please enter a valid name.',
      isEmail: false,
      isPhone: false,
      setNextStep: false,
      customValid: false,
      msgFadeOut: false,
      success: false//this is a success callback that you may call, make sure redir is false
   };
   var options = $.extend(defaults, options);
   
   var obj = options.obj;
   var objInput = options.input;
   var enteredName = objInput.val();
   var email = [true, 'bogus@fake.com', false];
   if (options.isEmail) {
      email = validateEmail(enteredName);
   }
   var vPhone = [true, false, false];
   if (options.isPhone) {
      vPhone = validatePhoneNumber(enteredName);
   }
   var $errorDiv = $(options.errorDiv);
   $errorDiv.hide();
   if (options.customValid && options.customValid != 'none') {
      if (!options.customValid.call(this)) {
         $errorDiv.show(200).html(options.errorMsg);
         if (options.msgFadeOut) {
            setTimeout(function(){
               $errorDiv.hide(400);
            }, 10000);
         }
         return false;
         
      } else {
         $errorDiv.html('').hide();
         if (options.redir) {
            showPane(options.redir);
            
            if (options.redirTitle) {
               changePaneTitle(options.redirTitle);
            }
         } else if (options.success) {
            options.success.call(this);
         }
         return true;
      }
   } else if (enteredName == '' || !enteredName || enteredName == options.noName || !email[0] || !vPhone[0]) {
   
      if (email[2]) {
         options.errorMsg = email[2];
      }
      if (!vPhone[0]) {
         options.errorMsg = vPhone[1];
      }
      $errorDiv.show(200).html(options.errorMsg);
      if (options.msgFadeOut) {
         setTimeout(function(){
            $errorDiv.hide(400);
         }, 10000);
      }
      return false;
      
   } else {
      $errorDiv.html('').hide();
      if (options.redir) {
         showPane(options.redir);
         
         if (options.redirTitle) {
            changePaneTitle(options.redirTitle);
         }
         
      } else if (options.success) {
         options.success.call(this);
      }
      
      validateTutNext = true;
      
      if (options.setNextStep) {
         setLiveStep('next');
      }
      
      return true;
   }
}

/**
 * example implementation
 *
 $('#nextPaneClick').validateInput({
 noName: 'Enter Site Name Here',
 redir: 'pane2',
 input: '#inputName',
 errorDiv: '#errorDiv',
 errorMsg: 'Please enter a valid name.'
 });
 *
 */
(function($){

   $.fn.validateCheckOpts = function(options){
   
      var defaults = {
         selectOpts: '.checkboxesClass',
         errorDiv: '#errorDiv',
         errorMsg: 'Please select an option.',
         redir: false,
         setNextStep: false,
         redirTitle: false,
         msgFadeOut: true
      };
      var options = $.extend(defaults, options);
      
      return this.each(function(){
      
         var obj = $(this);
         obj.click(function(){
            _validateCheckOpts({
               selectOpts: options.selectOpts,
               errorDiv: options.errorDiv,
               errorMsg: options.errorMsg,
               redir: options.redir,
               setNextStep: options.setNextStep,
               redirTitle: options.redirTitle,
               msgFadeOut: options.msgFadeOut
            });
         });
         
      });
   };
   
})(jQuery);
function _validateCheckOpts(options){

   var defaults = {
      selectOpts: '.checkboxesClass',
      errorDiv: '#errorDiv',
      errorMsg: 'Please select an option.',
      redir: false,
      setNextStep: false,
      redirTitle: false,
      msgFadeOut: false
   };
   var options = $.extend(defaults, options);
   var $errorDiv = $(options.errorDiv);
   $errorDiv.hide();
   var selectedElms = $(options.selectOpts + ':checked').length;
   if (selectedElms == 0) {
      $errorDiv.show().html(options.errorMsg);
      if (options.msgFadeOut) {
      
         setTimeout(function(){
            $errorDiv.fadeOut(400);
         }, 10000);
      }
      return false;
   } else {
      $errorDiv.html('').hide();
      if (options.redir) {
         showPane(options.redir);
      }
      if (options.redirTitle) {
         changePaneTitle(options.redirTitle);
      }
      
      return true;
   }
}
/**
 * example implementation
 *
 $('#nextPaneClick').validateCheckOpts({
 checkboxes: '.checkboxesClass',
 errorDiv: '#errorDiv',
 errorMsg: 'Please select an option.',
 redir: 'pane2'
 });
 *
 */
(function($){

   $.fn.validateSelect = function(options){
   
      var defaults = {
         errorDiv: '#errorDiv',
         errorMsg: 'Please select a site.',
         redir: false,
         setNextStep: false,
         redirTitle: false,
         noAcceptVal: '',
         msgFadeOut: false
      };
      var options = $.extend(defaults, options);
      
      return this.each(function(){
      
         var obj = $(this);
         obj.change(function(){
            var selectedVal = obj.find('option:selected').val();
            _validateSelect({
               selectedVal: selectedVal,
               errorDiv: options.errorDiv,
               errorMsg: options.errorMsg,
               redir: options.redir,
               setNextStep: options.setNextStep,
               redirTitle: options.redirTitle,
               noAcceptVal: options.noAcceptVal,
               msgFadeOut: options.msgFadeOut
            });
         });
         
      });
   };
   
})(jQuery);

function _validateSelect(options){

   var defaults = {
      selectedVal: '',
      errorDiv: '#errorDiv',
      errorMsg: 'Please select a site.',
      redir: false,
      setNextStep: false,
      redirTitle: false,
      noAcceptVal: '',
      msgFadeOut: false
   };
   var options = $.extend(defaults, options);
   selectedVal = options.selectedVal;
   if (selectedVal == options.noAcceptVal) {
      $(options.errorDiv).show().html(options.errorMsg);
      if (options.msgFadeOut) {
         setTimeout(function(){
            $(options.errorDiv).fadeOut(400);
         }, 10000);
      }
      return false;
   } else {
      $(options.errorDiv).html('');
      if (options.redir) {
         showPane(options.redir);
      }
      if (options.redirTitle) {
         changePaneTitle(options.redirTitle);
      }
      return true;
   }
}
/**
 * example implementation
 *
 $('#selectElm').validateSelect({
 errorDiv: '#errorDiv',
 errorMsg: 'Please select an option.',
 redir: 'pane2',
 noAcceptVal: 'none'
 });
 *
 */
(function($){

   $.fn.validateSpecial = function(options){
   
      var defaults = {
         setNextStep: false,
         errorDiv: '#errorDiv',//return the error message from your validate function when unsuccessful
         validate: function(){//function to perform to validate, must return true or error msg
         },
         success: function(){//function to perform on success
         }
      };
      var options = $.extend(defaults, options);
      
      return this.each(function(){
      
         var obj = $(this);
         var cErrorDiv = $(options.errorDiv);
         
         obj.click(function(){
            var isSuccess = options.validate.call(this);
            if (isSuccess === true) {
               options.success.call(this);
               
            } else {
               cErrorDiv.html(isSuccess).show(400);
               setTimeout(function(){
                  cErrorDiv.hide(500);
               }, 10000);
               return false;
            }
         });
         
      });
   };
   
})(jQuery);

function validateEmail(email){
   var reg = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
   var returnVal = [];
   var errMsg;
   if (reg.test(email) == false) {
      returnVal[0] = false;//return if the email is invalid
      returnVal[1] = email;//return the email
      if (email && email != 'Email' && email != 'Email Address' && email != 'email' && email != 'email address') {
         errMsg = '"' + email + '" is not a valid email address.'
      } else {
         errMsg = 'Enter a valid email address.'
      }
      returnVal[2] = errMsg;//return an error message
   } else {
      returnVal[0] = true;//return if the email is valid
      returnVal[1] = email;//return the email
   }
   return returnVal;
}

/**
 *
 * @param {String} domain
 * @param {String} noAcceptVal
 */
function validateDomain(domain, noAcceptVal){
   var domainExts = ['.com', '.net', '.org', '.biz', '.coop', '.info', '.museum', '.name', '.pro', '.edu', '.gov', '.int', '.mil', '.ac', '.ad', '.ae', '.af', '.ag', '.ai', '.al', '.am', '.an', '.ao', '.aq', '.ar', '.as', '.at', '.au', '.aw', '.az', '.ba', '.bb', '.bd', '.be', '.bf', '.bg', '.bh', '.bi', '.bj', '.bm', '.bn', '.bo', '.br', '.bs', '.bt', '.bv', '.bw', '.by', '.bz', '.ca', '.cc', '.cd', '.cf', '.cg', '.ch', '.ci', '.ck', '.cl', '.cm', '.cn', '.co', '.cr', '.cu', '.cv', '.cx', '.cy', '.cz', '.de', '.dj', '.dk', '.dm', '.do', '.dz', '.ec', '.ee', '.eg', '.eh', '.er', '.es', '.et', '.fi', '.fj', '.fk', '.fm', '.fo', '.fr', '.ga', '.gd', '.ge', '.gf', '.gg', '.gh', '.gi', '.gl', '.gm', '.gn', '.gp', '.gq', '.gr', '.gs', '.gt', '.gu', '.gv', '.gy', '.hk', '.hm', '.hn', '.hr', '.ht', '.hu', '.id', '.ie', '.il', '.im', '.in', '.io', '.iq', '.ir', '.is', '.it', '.je', '.jm', '.jo', '.jp', '.ke', '.kg', '.kh', '.ki', '.km', '.kn', '.kp', '.kr', '.kw', '.ky', '.kz', '.la', '.lb', '.lc', '.li', '.lk', '.lr', '.ls', '.lt', '.lu', '.lv', '.ly', '.ma', '.mc', '.md', '.mg', '.mh', '.mk', '.ml', '.mm', '.mn', '.mo', '.mp', '.mq', '.mr', '.ms', '.mt', '.mu', '.mv', '.mw', '.mx', '.my', '.mz', '.na', '.nc', '.ne', '.nf', '.ng', '.ni', '.nl', '.no', '.np', '.nr', '.nu', '.nz', '.om', '.pa', '.pe', '.pf', '.pg', '.ph', '.pk', '.pl', '.pm', '.pn', '.pr', '.ps', '.pt', '.pw', '.py', '.qa', '.re', '.ro', '.rw', '.ru', '.sa', '.sb', '.sc', '.sd', '.se', '.sg', '.sh', '.si', '.sj', '.sk', '.sl', '.sm', '.sn', '.so', '.sr', '.st', '.sv', '.sy', '.sz', '.tc', '.td', '.tf', '.tg', '.th', '.tj', '.tk', '.tm', '.tn', '.to', '.tp', '.tr', '.tt', '.tv', '.tw', '.tz', '.ua', '.ug', '.uk', '.um', '.us', '.uy', '.uz', '.va', '.vc', '.ve', '.vg', '.vi', '.vn', '.vu', '.ws', '.wf', '.ye', '.yt', '.yu', '.za', '.zm', '.zw'];
   var allowDomainExt = false;
   var thisExt = domain.slice(domain.lastIndexOf('.'));
   var i = 0;
   if (thisExt && !domain.match(/\s/)) {
      while (allowDomainExt == false) {
         if (thisExt == domainExts[i]) {
            allowDomainExt = true;
         } else if (i == domainExts.length - 1) {
            allowDomainExt = 'false';
         }
         i++
      }
   }
   
   if (!domain || domain == noAcceptVal) {
      return [false, 'Please enter a domain name.'];
   } else if (domain.match(/\s/)) {
      return [false, 'A domain cannot have spaces.'];
   } else if (!allowDomainExt || allowDomainExt == 'false') {
      return [false, 'Your domain must contain an extension like .com, .net, .org, .biz, etc.'];
   } else {
      return [true, domain];
   }
}

/** function: validate_youtube_url
 Returns: array(valid URI:Boolean, Error Message or Video ID:String, match results:Array)
 */
function validateYoutubeUrl(str, protocol){
   if (!protocol && protocol != '') {
      protocol = '(http://)|(http://www.)|(www.)';
   }
   protocol = protocol.replace(/\//g, '\/', protocol).replace(/\./g, '\.');
   protocol = (protocol != '') ? '^(' + protocol + ')' : protocol;
   match_exp = new RegExp(protocol + 'youtube\.com\/(.+)(v=.+)', 'gi');
   var matches = match_exp.exec(str);
   if (!matches || matches.length < 3) {
      return false;//Array(false, 'Invalid URI', matches);
   } else {
      var qs = matches[matches.length - 1].split('&');
      var vid = false;
      for (i = 0; i < qs.length; i++) {
         var x = qs[i].split('=');
         if (x[0] == 'v' && x[1]) {
            vid = x[1];
            return true;//Array(true, vid, matches);
         } else {
            return false;//Array(false, 'Missing ID', matches);
         }
      }
      return false;//Array(false, false, false);
   }
}

function validatePhoneNumber(phone){
   if (phone) {
      var numbers = stripNumbers(phone);
      var returnArray = [];
      if (phone.match(/[a-z]/)) {
         returnArray[0] = false;
         returnArray[1] = 'Invalid phone number. May not contain letters a to z.';
         returnArray[2] = phone;
      } else if (numbers.length < 6) {//7 are the minimum. 6 because the array starts at 0
         returnArray[0] = false;
         returnArray[1] = 'Invalid phone number. Not enough numbers.';
         returnArray[2] = phone;
      } else {
         returnArray[0] = true;
         returnArray[1] = false;
         returnArray[2] = phone;
      }
      return returnArray;
   } else {
      return [false, 'Please enter a valid phone number.', ''];
   }
}

function validateRadios(options){
   var defaults = {
      selectRadios: null,
      errorDiv: null,
      errorMsg: null,
      msgFadeOut: false
   };
   var options = $.extend(defaults, options);
   var $errorDiv = $(options.errorDiv);
   if ($(options.selectRadios + ':checked').length > 0) {
      $errorDiv.hide().html('');
      return true;
   } else {
      $errorDiv.show().html(options.errorMsg);
      if (options.msgFadeOut) {
      
         setTimeout(function(){
            $errorDiv.fadeOut(400);
         }, 10000);
      }
      return false;
   }
}


function validateForm(options){

   var defaults = {
      fields: [],//array of a jQuery selector for each form field
      operations: [],//the validation operation the field will use, sequence of array must match fields to align an op to it's field. options are input, email, checkbox, select, or a special function, must return Boolean true or false
      msgs: [],//the error msgs the field will use, sequence of array must match fields to align a msg to it's field.
      msgConts: [],//optional error container, sequence of array must match fields to align a container to its msg.
      trigger: false,//jQuery DOM element to trigger the validation
      success: false,//a callback to perform when the validation is all true
      fail: false//a callback to perform when any validation is false
   };
   var options = $.extend(defaults, options);
   
   var fld = options.fields, ops = options.operations, trig = options.trigger, msgs = options.msgs, msgConts = options.msgConts;
   var trigId = (trig.length) ? trig.attr('id') : 'Form';
   
   for (var i = 0; i < fld.length; i++) {
   
      if (!$(fld[i]).is('textarea')) {
         $(fld[i]).keypress(function(e){
            if (getKeyPress(e) == 'enter') {
               if (trig.length) {
                  trig.click();
               } else {
                  runValidate();
               }
               e.preventDefault();
            }
         });
      }
      //create all the warning containters
      if (!msgConts[i]) createErrorMsg(i);
   }
   
   function createErrorMsg(i){
      if ($('#validate_' + trigId + '_ErrorMsg_' + i).length == 0) {
         var newMsg = $('<div></div>').attr('id', 'validate_' + trigId + '_ErrorMsg_' + i).addClass('warningDiv').insertAfter(fld[i]).show();
      }
      return '#validate_' + trigId + '_ErrorMsg_' + i;
   }
   
   function runValidate(eventO){
   
      var allValidators = [];
      
      for (var i = 0; i < fld.length; i++) {
         var $fld = $(fld[i]), op = ops[i];
         if ($fld.length > 0) {
         
            if (op == 'input') {
               var msgCont;
               if (msgConts[i]) {
                  msgCont = msgConts[i];
               } else {
                  msgCont = createErrorMsg(i);
               }
               var msg;
               if (msgs[i]) {
                  msg = msgs[i];
               } else {
                  msg = 'This field is required.';
               }
               var isValid = _validateInput({
                  input: $fld,
                  errorDiv: msgCont,
                  errorMsg: msg,
                  noName: false,
                  msgFadeOut: true
               });
               allValidators.push(isValid);
               
            } else if (op == 'email') {
               var msgCont;
               if (msgConts[i]) {
                  msgCont = msgConts[i];
               } else {
                  msgCont = createErrorMsg(i);
               }
               var msg;
               if (msgs[i]) {
                  msg = msgs[i];
               } else {
                  msg = 'Enter a valid email.';
               }
               var isValid = _validateInput({
                  input: $fld,
                  errorDiv: msgCont,
                  errorMsg: msg,
                  isEmail: true,
                  noAcceptVal: '',
                  msgFadeOut: true
               });
               allValidators.push(isValid);
               
            } else if (op == 'phone') {
               var msgCont;
               if (msgConts[i]) {
                  msgCont = msgConts[i];
               } else {
                  msgCont = createErrorMsg(i);
               }
               
               var msg;
               if (msgs[i]) {
                  msg = msgs[i];
               } else {
                  msg = 'Enter a valid phone number.';
               }
               var isValid = _validateInput({
                  input: $fld,
                  errorDiv: msgCont,
                  errorMsg: msg,
                  isPhone: true,
                  noAcceptVal: '',
                  msgFadeOut: true
               });
               allValidators.push(isValid);
               
            } else if (op == 'select') {
               var msgCont;
               if (msgConts[i]) {
                  msgCont = msgConts[i];
               } else {
                  msgCont = createErrorMsg(i);
               }
               var msg;
               if (msgs[i]) {
                  msg = msgs[i];
               } else {
                  msg = 'Select an option.';
               }
               
               var selectedVal = $fld.find('option:selected').val();
               
               var isValid = _validateSelect({
                  selectedVal: selectedVal,
                  errorDiv: msgCont,
                  errorMsg: msg,
                  msgFadeOut: true,
                  noAcceptVal: 'false'//the value of the options that are not allowed must always be false
               });
               
               allValidators.push(isValid);
            } else if (op == 'checkbox') {
               var msgCont;
               if (msgConts[i]) {
                  msgCont = msgConts[i];
               } else {
                  msgCont = createErrorMsg(i);
               }
               
               var msg;
               if (msgs[i]) {
                  msg = msgs[i];
               } else {
                  msg = 'Check the box.';
               }
               
               var isValid = _validateCheckOpts({
                  selectOpts: fld[i],
                  errorDiv: msgCont,
                  errorMsg: msg,
                  msgFadeOut: true
               });
               
               allValidators.push(isValid);
               
            } else if (op == 'radio') {//currently not supporting radios. TODO: write a radio validate script
               var msgCont;
               if (msgConts[i]) {
                  msgCont = msgConts[i];
               } else {
                  msgCont = createErrorMsg(i);
               }
               var msg;
               if (msgs[i]) {
                  msg = msgs[i];
               } else {
                  msg = 'Select an option.';
               }
               var isValid = validateRadios({
                  selectRadios: fld[i],
                  errorDiv: msgCont,
                  errorMsg: msg,
                  msgFadeOut: true
               });
               
               allValidators.push(isValid);
            } else if (typeof op == 'function') {//special function, must return Boolean true or false
               var msgCont;
               if (msgConts[i]) {
                  msgCont = msgConts[i];
               } else {
                  msgCont = createErrorMsg(i);
               }
               var msg;
               if (msgs[i]) {
                  msg = msgs[i];
               } else {
                  msg = 'Invalid.';
               }
               
               var opIsValid = op.call(this, fld[i]);
               var $errorDiv = $(msgCont);
               
               if (!opIsValid) {
                  $errorDiv.show().html(msg);
                  
                  setTimeout(function(){
                     $errorDiv.fadeOut(400);
                  }, 10000);
                  
               } else {
                  $errorDiv.fadeOut(400);
               }
               allValidators.push(opIsValid);
            } else {
               /*log(typeof op);
               log(op);*/
            }
            
         }
      };
      var allValid = true;
      for (var i = 0; i < allValidators.length; i++) {
         if (allValidators[i] == false) {
            allValid = false;
         }
      }
      
      if (allValid && options.success) {
         options.success.call(this, eventO);//return the event object
      } else if (options.fail) {
         options.fail.call(this, eventO);//return the event object
      }
      
      return allValid;
   }
   
   if (trig.length) {
      trig.click(function(e){//return the event object
         runValidate(e);//return the event object
      });
   } else {//if there is not trigger we assume this is to be ran immediately.
      return runValidate();
   }
   
}

/**
 * onValidateForm
 * @param {Object} options
 */
jQuery.fn.onValidateForm = function(options){

   var defaults = {
      fields: [],//array of a jQuery selector for each form field
      operations: [],//the validation operation the field will use, sequence of array must match fields to align an op to it's field. options are input, email, checkbox, select, or a special function, must return Boolean true or false
      msgs: [],//the error msgs the field will use, sequence of array must match fields to align an msg to it's field.
      msgConts: [],//optional error container, sequence of array must match fields to align a container to its msg.
      success: false,//a callback to perform when the validation is all true
      fail: false//a callback to perform when any validation is false
   };
   var options = $.extend(defaults, options);
   
   return this.each(function(){
   
      validateForm({
         fields: options.fields,
         operations: options.operations,
         msgs: options.msgs,
         msgConts: options.msgConts,
         trigger: $(this),
         success: options.success,
         fail: options.fail
      });
      
   });
   
};

