var VF = VF || { };

VF.getValue = function(elem) {
      var i, len;
      if (!elem) {
            return null;

      } else if (!elem.nodeName) { // radio
            for (i = 0, len = elem.length; i < len; i++) {
                  if (elem[i].checked) {
                        return elem[i].value;
                  }
            }
            return null;

      } else if (elem.nodeName.toLowerCase() === 'select') {
            var index = elem.selectedIndex, options = elem.options;

            if (index < 0) {
                  return null;

            } else if (elem.type === 'select-one') {
                  return options[index].value;
            }

            for (i = 0, values = [], len = options.length; i < len; i++) {
                  if (options[i].selected) {
                        values.push(options[i].value);
                  }
            }
            return values;

      } else if (elem.type === 'checkbox') {
            return elem.checked;

      } else if (elem.type === 'radio') {
            return VF.getValue(elem.form.elements[elem.name]);

      } else {
            return elem.value.replace(/^\s+|\s+$/g, '');
      }
}


VF.addError = function(elem, message) {
      if (elem.focus) {
            elem.focus();
      }
      if (message) {
            alert(message);
      }
}


VF.validateForm = function(sender) {
      var form = sender.form || sender;
      for (var i = 0; i < form.elements.length; i++) {
            var elem = form.elements[i];
            if (!(elem.nodeName.toLowerCase() in {input:1, select:1, textarea:1}) || (elem.type in {hidden:1, submit:1, image:1, reset: 1}) || elem.disabled || elem.readonly) {
                  continue;
            }
            if (!VF.validateControl(elem)) {
                  return false;
            }
      }
      return true;
}

VF.validateControl = function(elem, rules, onlyCheck) {
      rules = rules || eval('[' + (elem.getAttribute('data-validation-rules') || '') + ']');
      for (var id = 0, len = rules.length; id < len; id++) {
            var rule = rules[id], op = rule.op.match(/(~)?([^?]+)/);
            rule.neg = op[1];
            rule.op = op[2];
            rule.condition = !!rule.rules;
            var el = rule.control ? elem.form.elements[rule.control] : elem;

            var success = VF.validateRule(el, rule.op, rule.arg);
            if (success === null) { continue; }
            if (rule.neg) { success = !success; }
                                   
            if (rule.condition && success) {
                  if (!VF.validateControl(elem, rule.rules, onlyCheck)) {
                        return false;
                  }
            } else if (!rule.condition && !success) {       
                  if (el.disabled) { continue; }
                  if (!onlyCheck) {
                        VF.addError(el, rule.msg.replace('%value', VF.getValue(el)));
                  }
                  return false;
            }
      }
      return true;
}


VF.validateRule = function(elem, op, arg) {
      var val = VF.getValue(elem);
      //if(elem.getAttribute){
      //      if (val === elem.getAttribute('data-validation-empty-value')) { val = null; }
      //}
      if (op.charAt(0) === ':') {
            op = op.substr(1);
      }
      op = op.replace('::', '_');
      return VF.validators[op] ? VF.validators[op](elem, arg, val) : null;
}



VF.validators = {
      filled: function(elem, arg, val) {
            return val !== '' && val !== false && val !== null;
      },

      valid: function(elem, arg, val) {
            //return VF.validateControl(elem, null, true);
            return null;
      },

      equal: function(elem, arg, val) {
            arg = arg instanceof Array ? arg : [arg];
            for (var i = 0, len = arg.length; i < len; i++) {
                  if (val == (arg[i].control ? VF.getValue(elem.form.elements[arg[i].control]) : arg[i])) {
                        return true;
                  }
            }
            return false;
      },

      minLength: function(elem, arg, val) {
            return val.length >= arg;
      },

      maxLength: function(elem, arg, val) {
            return val.length <= arg;
      },

      length: function(elem, arg, val) {
            if (typeof arg !== 'object') {
                  arg = [arg, arg];
            }
            return (arg[0] === null || val.length >= arg[0]) && (arg[1] === null || val.length <= arg[1]);
      },

      email: function(elem, arg, val) {
            return (/^[^@\s]+@[^@\s]+\.[a-z]{2,10}$/i).test(val);
      },

      url: function(elem, arg, val) {
            return (/^.+\.[a-z]{2,6}(\/.*)?$/i).test(val);
      },

      regexp: function(elem, arg, val) {
            var parts = arg.match(/^\/(.*)\/([imu]*)$/);
            if (parts) { try {
                  return (new RegExp(parts[1], parts[2].replace('u', ''))).test(val);
            } catch (e) {} }
            return;
      },

      pattern: function(elem, arg, val) {
            return (new RegExp(arg)).test(val);
      },

      integer: function(elem, arg, val) {
            return (/^-?[0-9]+$/).test(val);
      },

      float: function(elem, arg, val) {
            return (/^-?[0-9]*[.,]?[0-9]+$/).test(val);
      },

      range: function(elem, arg, val) {
            return (arg[0] === null || parseFloat(val) >= arg[0]) && (arg[1] === null || parseFloat(val) <= arg[1]);
      },

      submitted: function(elem, arg, val) {
            //return elem.form['vf-submittedBy'] === elem;
      }
}



$(document).ready(function(){  
      $('form').submit(function(){
            return VF.validateForm(this);
      })
})

