//////////////////////////////////////////////////////////////////////
//////////// CUSTOM FUNCTIONS
//////////////////////////////////////////////////////////////////////

function require_input(formElement) {
  $(formElement).css('border', '1px solid red');
  var formError = $(formElement).siblings(".formerror");
  formError.text("Red fields are required. Please enter a valid name, company, and email address.");
  formError.css("display","inline");
}

function reset_input(formElement) {
  $(formElement).css('border', '1px solid #26A0D9');
  var formError = $(formElement).siblings(".formerror");
  formError.text("");
  formError.css("display","none");
}


//////////////////////////////////////////////////////////////////////
//////////// UTILITY FUNCTIONS
//////////////////////////////////////////////////////////////////////

function token(str) {
  if(str.match(/^[\s]+|[\f|\n|\r|\n\r|\t|\v]|\s{2,}|[\s]+$/g)) return false;
  else return true;
}

function run_regex(formElement, exp) {
  if(typeof(exp) !== "string") return false;
  if(typeof(formElement.value) !== "string") return false;

  var re = new RegExp(exp, "g");

  if(token(formElement.value) === false) {
    require_input(formElement);
    return false;
  }

  if(formElement.value.match(re)) {
    reset_input(formElement);
    return true;
  } else {
    require_input(formElement);
    return false;
  }
}


//////////////////////////////////////////////////////////////////////
//////////// VALIDATION FUNCTIONS
//////////////////////////////////////////////////////////////////////

// require              : Require tokenized input
// require_equal        : Require two equal tokenized inputs
// require_unique       : Require tokenized input that differs from a default
// require_selected     : Require a non-default tokenized option on a select dropdown
// require_email        : Require a valid email address (basic x@x.x format)
// require_int          : Require an integer (signed or unsigned)
// require_int_bounded  : Require an integer within bounds (signed or unsigned)
// require_cc_num       : Require a valid credit card number
// require_zip          : Require a valid US zip code


function require(formElement, minChars, maxChars) {
  if(typeof(formElement.value) !== "string") return false;
  if(typeof(minChars) !== "number") return false;
  if(typeof(maxChars) !== "number") return false;

  if(token(formElement.value) === false) {
    require_input(formElement);
    return false;
  }

  if(formElement.value !== "" && 
     formElement.value.length > minChars && 
     formElement.value.length < maxChars) 
  {
    reset_input(formElement);
    return true;
  } else {
    require_input(formElement);
    return false;
  }
}


function require_equal(formElement1, formElement2, minChars, maxChars) {
  if(typeof(formElement1.value) !== "string") return false;
  if(typeof(formElement2.value) !== "string") return false;
  if(typeof(minChars) !== "number") return false;
  if(typeof(maxChars) !== "number") return false;

  if(token(formElement1.value) === false) {
    require_input(formElement1);
    require_input(formElement2);
    return false;
  }

  if(formElement1.value !== "" && 
     formElement1.value.length > minChars && 
     formElement1.value.length < maxChars) 
  {
    if(formElement1.value === formElement2.value) {
      reset_input(formElement1);
      reset_input(formElement2);
      return true;
    }
  }
  require_input(formElement1);
  require_input(formElement2);
  return false;
}


function require_unique(formElement, defaultString, minChars, maxChars) {
  if(typeof(formElement.value) !== "string") return false;
  if(typeof(defaultString) !== "string") return false;
  if(typeof(minChars) !== "number") return false;
  if(typeof(maxChars) !== "number") return false;

  if(token(formElement.value) === false) {
    require_input(formElement);
    return false;
  }

  if(formElement.value !== "" && 
     formElement.value.length > minChars && 
     formElement.value.length < maxChars && 
     formElement.value !== defaultString) 
  {
    reset_input(formElement);
    return true;
  } else {
    require_input(formElement);
    return false;
  }
}


function require_selected(formElement, defaultString) {
  if(typeof(formElement.value) !== "string") return false;
  if(typeof(defaultString) !== "string") return false;

  if(token(formElement.value) === false) {
    require_input(formElement);
    return false;
  }

  if(formElement.value !== "" && 
     formElement.value.length > 0 && 
     formElement.value !== defaultString)
  {
    reset_input(formElement);
    return true;
  } else {
    require_input(formElement);
    return false;
  }
}


function require_email(formElement) {
  if(typeof(formElement.value) !== "string") return false;
  var r = run_regex(formElement, "^[^@]+@[^@]+\\.[^@]+[^\\.]$");
  return r;
}


function require_int(formElement) {
  if(typeof(formElement.value) !== "string") return false;
  var r = run_regex(formElement, "^[\\-|\\+|\\d]\\d+$");
  return r;
}


function require_int_bounded(formElement, minInt, maxInt) {
  if(typeof(formElement.value) !== "string") return false;
  if(typeof(minInt) !== "number") return false;
  if(typeof(maxInt) !== "number") return false;

  var r = run_regex(formElement, "^[\\-|\\+|\\d]\\d+$");

  if(!r) { 
    return r;
  } else {
    if(parseInt(formElement.value) < minInt || parseInt(formElement.value) > maxInt) {
      require_input(formElement);
      return false; 
    }
    return r;
  }
}


function require_cc_num(formElement) {
  if(typeof(formElement.value) !== "string") return false;
  var r = run_regex(formElement, "^\\d{10,20}?$");
  return r;
}


function require_zip(formElement) {
  if(typeof(formElement.value) !== "string") return false;
  var r = run_regex(formElement, "^\\d{5}$");
  return r;
}
