/////////////////////////////////////////////////////////////////////
// Constants
var ETAPINTEGERREGEXP = /^\d+$/;
var ETAPDATESEPREGEXP = /[\/-]/;
var ETAPCANADIANPOSTREGEXP = /^[A-Z][0-9][A-Z] ?[0-9][A-Z][0-9]$/i;
var ETAPCANADIANPOSTEXCLUDE = /(^W)|(^Z)|(D|F|I|O|Q)/i;
var ETAPUKPOSTREGEXP = /^[A-Z]([A-Z])?[A-Z0-9]([A-Z0-9])? ?[0-9][A-Z][A-Z]$/i;
var ETAPSTATECODEDELIM = "|";
var ETAPUSSTATECODES = "|AL|AK|AS|AZ|AR|CA|CO|CT|DE|DC|FM|FL|GA|GU|HI|ID|IL|IN|IA|KS|KY|LA|ME|MH|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|MP|OH|OK|OR|PW|PA|PR|RI|SC|SD|TN|TX|UT|VT|VI|VA|WA|WV|WI|WY|AE|AA|AP|";
var ETAPCASTATECODES = "|AB|BC|MB|NB|NL|NS|NT|NU|ON|PE|QC|SK|YT|";
var ETAPAUSTATECODES = "|ACT|NSW|NT|QLD|SA|TAS|VIC|WA|";
var ETAPMXSTATECODES = "|AGS|BC|BCS|CAM|CHIH|CHIS|COAH|COL|DF|DGO|GRO|GTO|HGO|JAL|MEX|MICH|MOR|NAY|NL|OAX|PUE|QRO|QROO|SIN|SLP|SON|TAB|TAM|TLAX|VER|YUC|ZAC|";
var ETAPSTATECODES = ETAPUSSTATECODES + ETAPCASTATECODES.substring(1) + ETAPAUSTATECODES.substring(1) + ETAPMXSTATECODES.substring(1);


/////////////////////////////////////////////////////////////////////
// Utilities

// Removes all characters which appear in string bag from string s.
function stripCharsInBag(s, bag)
{
    if (s == null) return "";

    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.
    var returnString = "";
    for (var i = 0; i < s.length; i++)
    {
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }
    
    return returnString;
}

// Disables all submit buttons in the given form
function disableSubmits(form)
{
  if (!form) return;
  for (var i = 0 ; i < form.elements.length ; i++)
  {
    if (form.elements[i].type == "submit")
    {
      form.elements[i]._etapWasDisabled = form.elements[i].disabled;
      form.elements[i].disabled = true;
    }
  }
}

// Enables all submit buttons in the given form
function enableSubmits(form)
{
  if (!form) return;
  for (var i = 0 ; i < form.elements.length ; i++)
  {
    if (form.elements[i].type == "submit")
    {
      form.elements[i].disabled = form.elements[i]._etapWasDisabled != undefined ? form.elements[i]._etapWasDisabled : false;
    }
  }
}


////////////////////////////////////////////////////////////////////
// Validators

// Integer validator
function jqueryValidateInteger(value, element, params)
{
    return ETAPINTEGERREGEXP.test(value);
}
$.validator.addMethod("integer", jqueryValidateInteger, "This field must contain an integer value");

// Month/Day Values validator
function jqueryValidateMonthDay(value, element, params)
{
  // Just duplicate date validation, with a year
  return !/Invalid|NaN/.test(new Date(value + "/2008"));
}
$.validator.addMethod("monthday", jqueryValidateMonthDay, "This field must contain a valid month/day value");

// Postal Code validator
function jqueryValidatePostalCode(value, element, params)
{
    // Determine the country that we'll use for validation, if possible
    var countryCode = "";
    if (self.countrySelectorData && self.countrySelectorData.boxId)
    {
      var countryBox = document.getElementById(self.countrySelectorData.boxId);
      if (countryBox) countryCode = countryBox.value;
    }
    
    // Default to US if empty
    if (!countryCode) countryCode = "US";
    if (countryCode.toUpperCase) countryCode = countryCode.toUpperCase();
    
    // Test value based on country
    var normalizedZip = stripCharsInBag(value, "- ");
    if (countryCode == "US")
    {
      if (!normalizedZip) return false;
      return jqueryValidateInteger(normalizedZip) && ((normalizedZip.length == 5) || (normalizedZip.length == 9));
    }
    else if (countryCode == "AU" || countryCode == "NZ")
    {
      if (!normalizedZip) return false;
      return jqueryValidateInteger(normalizedZip) && ((normalizedZip.length == 4) || (normalizedZip.length == 3));
    }
    else if (countryCode == "CA")
    {
      if (!value) return false;
      return ETAPCANADIANPOSTREGEXP.test(value) && !ETAPCANADIANPOSTEXCLUDE.test(value)
    }
    else if (countryCode == "UK")
    {
      if (!value) return false;
      return ETAPUKPOSTREGEXP.test(value);
    }
    
    // Didn't find country, don't validate
    return true;
}
$.validator.addMethod("postalCode", jqueryValidatePostalCode, "This field must contain a valid postal code");

// State validator
function jqueryValidateState(value, element, params)
{
    //return (ETAPSTATECODES.indexOf(ETAPSTATECODEDELIM + value.toUpperCase() + ETAPSTATECODEDELIM) != -1);
    // Just make sure the "first" option - none selected, isn't what's selected
    return element.selectedIndex != 0;
}
$.validator.addMethod("state", jqueryValidateState, "This field must contain a valid state");

// CVV2 validator
function jqueryValidateCVV2(value, element, params)
{
    return !value || (jqueryValidateInteger(value) && (value.length == 3 || value.length == 4));
}
$.validator.addMethod("cvv2", jqueryValidateCVV2, "This field must contain a valid CVV2 value");

// Password validator
function jqeryValidatePassword(value, element, params)
{
    return value.length == 0 || value.length >= 6; // Minimum length
}
$.validator.addMethod("password", jqeryValidatePassword, "This field must be at least 6 characeters");

// HTML Editor content validator
function jqueryValidateHtmlEditor(value, element, params)
{
    // If there's no ID or editor, just return true
    if (!element || !element.id) return true;
    var editor = tinyMCE.get(element.id);
    if (!editor) return true;
    
    // Just ensure that there's some content
    return editor.getContent();
}
$.validator.addMethod("htmlContent", jqueryValidateHtmlEditor, "This field must contain a value");

