var formattedInput, maxLength;
var truncated;

var hold = false;

// Third argument must be passed by caller when expectedFormat argument is 'currency' or 'multi'
// Optional fourth argument can be used to disable alert window

function checkFormat(userInput,expectedFormat) {
  var pattern,error;

  truncated = false;

  if (arguments.length > 2) {
    if (arguments[2] > 0) maxLength = arguments[2];
    else maxLength = 1
  }

  switch (expectedFormat) {
    case "alphanum":
      pattern = /^\w+$/;
      break
    case "currency":
      pattern = /^[$]?0*(\d*)(\.\d*)?$/;
      break
    case "date":
      pattern = /^((0?[1-9])|(1[0-2]))\s*[\s-\/]\s*((0?[1-9])|([1-2]\d)|(3[0-1]))\s*[\s-\/]\s*((\d{1,2})|(19\d{2})|(2\d{3}))$/;
      break
    case "day":
      pattern = /^((0?\d)|([1-2]\d)|(3[0-1]))$/;
      break
    case "email":
      pattern = /^((\w|[\.\-])+@((\w|[\.\-])+\.[a-zA-Z]{2,4})|(\[?[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\]?))$/;
      break
    case "mcalpha":
      pattern = /^[a-zA-Z]$/;
      break
    case "multi":
      userInput = winToASCII(userInput);

      pattern = /^([\s\x21-\x7E]+)$/;
      break
    case "nonempty":
      pattern = /\S+/;
      break
    case "number":
      pattern = /^(\d+)$/;
      break
    case "numeric":
      pattern = /^(\d+)$/;
      break
    case "phone":
      pattern = /^\(?(\d{3})\)?[\s-\.]?(\d{3})[\s-\.]?(\d{4})$/;
      break
    case "ssn":
      pattern = /^(\d{3})[\s-]?(\d{2})[\s-]?(\d{4})$/;
      break
    case "zip":
      pattern = /(^\d{5}-?$)|(^\d{5}-?\d{4}$)/;
      break
  }

  var validFormat = pattern.test(userInput);

  if (validFormat) {
    hold = false;

    formattedInput = userInput;

    switch (expectedFormat) {
      case "currency":
        formattedInput = formattedInput.replace(/[$]/, "");
        formattedInput = formattedInput.replace(/,/, "");
        formattedInput = formattedInput.replace(/^0+([1-9])/, "$1");
        formattedInput = formattedInput.replace(/^0+/, "0");
        formattedInput = formattedInput.replace(/(^\d*$)/, "$1.00");
        formattedInput = formattedInput.replace(/(^\d*\.$)/, "$100");
        formattedInput = formattedInput.replace(/(^\d*\.\d$)/, "$10");
        formattedInput = formattedInput.replace(/(^\d*\.\d{2})\d+$/, "$1");
        formattedInput = formattedInput.replace(/^(\.\d{2})/, "0$1");

        if (formattedInput.length > maxLength + 3) {
          maxDollarAmt = "";
          error = "Dollar amount can't exceed $";

          for (var i=0; i < maxLength; i++) {
            maxDollarAmt = maxDollarAmt + "9"
          }
          error = error + maxDollarAmt + ".99"
        }
        else {
          return true
        }
        break
      case "date":
        result = pattern.exec(formattedInput);

        month = parseFloat(result[1]);
        day = parseFloat(result[4]);
        year = parseFloat(result[8]);

        if (year < 30) year = 2000 + year;
        else if (year < 100) year = 1900 + year;

        formattedInput = month + "/" + day + "/" + year;

        formattedInput = formattedInput.replace(/(^\d)[\/]/, "0$1/");
        formattedInput = formattedInput.replace(/[\/](\d)[\/]/, "/0$1/");

        if (month == 2 && day == 29 && ((year % 4) != 0)) {
          error = year + " is not a leap year!"
        }
        else if (month == 2 && day > 29) {
          ;
        }
        else if ((month == 4 || month == 6 || month == 9 || month == 11) && (day > 30)) {
          ;
        }
        else {
          return true
        }
        break
      case "day":
        formattedInput = parseInt(formattedInput);

        return true
      case "mcalpha":
        formattedInput = formattedInput.toLowerCase();

        minCharCode = 97;

        for (var i=minCharCode; i<minCharCode+maxLength; i++) {
          if (formattedInput == String.fromCharCode(i)) {
            return true
          }
        }

        if (maxLength > 1) {
          error = "Please enter letter from available choices '" + String.fromCharCode(minCharCode) + "' thru '" + String.fromCharCode((minCharCode + maxLength) - 1) + "'"
        }
        else {
          error = "Please enter the letter '" + String.fromCharCode(minCharCode) + "'"
        }
        break
      case "multi":
        formattedInput = formattedInput.replace(/^\s+/, "");
        formattedInput = formattedInput.replace(/\s+/g, " ");
        formattedInput = formattedInput.replace(/\s+$/, "");
	  
        if (formattedInput.length > maxLength) {
          error = "Warning: Input exceeds " + maxLength + "-character limit!\n\n" +
                  "Input has been truncated to fit within maximum field length."

          truncated = true
        }
        else {
          return true
        }
        break
      case "number":
        formattedInput = parseInt(formattedInput);

        return true
      case "phone":
        formattedInput = formattedInput.replace(/\(|\)/g, "");
        formattedInput = formattedInput.replace(pattern, "($1) $2-$3");

        return true
      case "ssn":
        formattedInput = formattedInput.replace(pattern, "$1-$2-$3");

        return true
      case "zip":
        formattedInput = formattedInput.replace(/(^\d{5})-?$/, "$1");
        formattedInput = formattedInput.replace(/(^\d{5})(\d{4}$)/, "$1-$2");

        return true
      default:
        return true
    }
  }
  else {
    hold = true;

    switch (expectedFormat) {
      case "alphanum":
        error = "Error: Invalid input format\n\n" +
                "Please re-enter as alpha-numeric value with no spaces";
        break
      case "currency":
        error = "Error: Invalid input format\n\n" +
                "Please re-enter as dollar amount (ex. 40.50, 370, etc.)";
        break
      case "date":
        error = "Error: Invalid date value\n\n" +
                "Please check input and enter date again as 'mm/dd/yyyy'";
        break
      case "day":
        error = "Error: Invalid value for day\n\n" +
                "Please re-enter number between 1 and 31";
        break
      case "email":
        error = "Error: Invalid e-mail format\n\n" +
                "Please re-enter e-mail address\n" +
                "(ex. 'name@mail.com')";
        break
      case "mcalpha":
        error = "Error: Invalid input format\n\n" +
                "Please re-enter as letter from available choices";
        break
      case "multi":
        pattern = /([^\s\x21-\x7E])/;

        result = pattern.exec(userInput);

        invalidChar = result[1];

        error = "Error: \"" + invalidChar + "\" is not a valid character\n\n" +
                "Only characters that appear on a standard keyboard\n" +
                "will be accepted\n\n" +
                "Please re-enter text with invalid character removed";
        break
      case "nonempty":
        error = "Error: Field requires a value";
        break
      case "numeric":
      case "number":
        error = "Error: Invalid input format\n\n" +
                "Please re-enter as numeric value";
        break
      case "phone":
        error = "Error: Invalid input format\n\n" +
                "Please re-enter area code and phone number";
        break
      case "ssn":
        error = "Error: Invalid Social Security Number format\n\n" +
                "Please check input and enter SSN again as '###-##-####'";
        break
      case "zip":
        error = "Error: Invalid input format\n\n" +
                "Please re-enter 5-digit zip code (4-digit suffix optional)";
        break
    }
  }

  if (arguments.length < 4) alert(error);

  hold = false;

  return false
}

function winToASCII(str) {
  var pattern;

  var winToASCIIChars = {
    "\x8A": "\x53",
    "\x8E": "\x5A",
    "\x9A": "\x73",
    "\x9E": "\x7A",
    "\xC0": "\x41",
    "\xC1": "\x41",
    "\xC2": "\x41",
    "\xC3": "\x41",
    "\xC4": "\x41",
    "\xC5": "\x41",
    "\xC8": "\x45",
    "\xC9": "\x45",
    "\xCA": "\x45",
    "\xCB": "\x45",
    "\xCC": "\x49",
    "\xCD": "\x49",
    "\xCE": "\x49",
    "\xCF": "\x49",
    "\xD1": "\x4E",
    "\xD2": "\x4F",
    "\xD3": "\x4F",
    "\xD4": "\x4F",
    "\xD5": "\x4F",
    "\xD6": "\x4F",
    "\xD9": "\x55",
    "\xDA": "\x55",
    "\xDB": "\x55",
    "\xDC": "\x55",
    "\xDD": "\x55",
    "\xE0": "\x61",
    "\xE1": "\x61",
    "\xE2": "\x61",
    "\xE3": "\x61",
    "\xE4": "\x61",
    "\xE5": "\x61",
    "\xE8": "\x65",
    "\xE9": "\x65",
    "\xEA": "\x65",
    "\xEB": "\x65",
    "\xEC": "\x69",
    "\xED": "\x69",
    "\xEE": "\x69",
    "\xEF": "\x69",
    "\xF0": "\x6F",
    "\xF1": "\x6E",
    "\xF2": "\x6F",
    "\xF3": "\x6F",
    "\xF4": "\x6F",
    "\xF5": "\x6F",
    "\xF6": "\x6F",
    "\xF9": "\x75",
    "\xFA": "\x75",
    "\xFB": "\x75",
    "\xFC": "\x75",
    "\xFD": "\x79",
    "\xFF": "\x79",
    "\u201C": "\x22",
    "\u201D": "\x22",
    "\u2018": "\x27",
    "\u2019": "\x27"
  };

  for (var winChar in winToASCIIChars) {
    pattern = new RegExp(winChar);

    str = str.replace(pattern, winToASCIIChars[winChar]);
  }

  return str;
}
