var V_NOT_BLANK     = 1;
var V_HTML_SAFE     = 2;
var V_IS_DATE       = 4;
var V_IS_NUMBER     = 8;
var V_IS_EMAIL      = 16;
var V_IS_TIME       = 32;



function trim(s)
{
    if (typeof s != "string")
        return s;

    var i = 0;
    var c = s.charAt(i);

    while (c == ' ')
        c = s.charAt(++i);

    s = s.substr(i, s.length - i);
    c = s.charAt(s.length - 1);
    i = 1;

    while (c == ' ')
        c = s.charAt(s.length - ++i);

    s = s.substr(0, s.length - i + 1);

    return s;
}


function isBlank(s)
{
    if (typeof s != "string")
        return false;
    else
        return trim(s) == "";
}


/*
    Validates a credit card number using Luhn mod 10.  See the following
    URL for details about the algorithm.

    http://www.beachnet.com/~hstiles/cardtype.html
*/
function isCreditCard(s)
{
    var len = s.length;
    var i = 0;
    var sum = 0;
    var dig = 0;
    var mul = 1;

    if (len > 19)
        return false;

    for (i = 0; i < len; i++)
    {
        dig = parseInt(s.substr(len - i - 1, 1));
        dig *= mul;
        (mul == 1) ? mul = 2 : mul = 1;

        if (dig < 10)
            sum += dig;
        else
            sum += 1 + (dig % 10);
    }

    return (sum % 10) == 0;
}


function isCorrectCardType(ct, cn)
{
    if (ct == "Visa")
    {
        return (cn.substr(0, 1) == "4")
    }

    if (ct == "MasterCard")
    {
        check = cn.substr(0, 2);
        return ((check == "51") || (check == "52") || (check == "53") || (check == "54") || (check == "55"))
    }

    if (ct == "American Express")
    {
        check = cn.substr(0, 2);
        return ((check == "34") || (check == "37"))
    }

    if (ct == "Discover")
    {
        return (cn.substr(0, 4) == "6011")
    }

    return false;
}


function isHTMLSafe(s)
{
    return (s.search(/[<>\"]/g) == -1);
}


function isDate(s)
{
    // checks dates in "m/d/y" format

    if (!/^(0?[1-9]|1[0-2])\/(0?[1-9]|[12][0-9]|3[01])\/\d{1,4}$/.test(s))
        return false;

    var dateParts = s.split("/");

    dateParts[0] = dateParts[0].match(/^0*(\d+)$/)[1];
    dateParts[1] = dateParts[1].match(/^0*(\d+)$/)[1];
    dateParts[2] = dateParts[2].match(/^0*(\d+)$/)[1];

    var m = parseInt(dateParts[0]) - 1; // months range 0-11
    var d = parseInt(dateParts[1]);
    var y = parseInt(dateParts[2]);

    var checkDate = new Date(y, m, d);

    return (checkDate.getMonth() == m) && (checkDate.getDate() == d) && ((checkDate.getFullYear() == y) || (checkDate.getYear() == y))
}

function isTime(s)
{
    // checks times in "hh:nn" and "hh:nn:ss" format
    //  1:10:15 okay
    // 01:10:15 okay
    //  1:10    okay
    // 13:10    not okay
    //  1:10 PM not okay

    return /^(0?[1-9]|1[0-2]):(0[0-9]|[1-5][0-9])(:(0[0-9]|[1-5][0-9]))?$/.test(s);
}

function isEmail(s)
{
    var checkTLD=1;
    var knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
    var emailPat=/^(.+)@(.+)$/;
    var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
    var validChars="\[^\\s" + specialChars + "\]";
    var quotedUser="(\"[^\"]*\")";
    var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
    var atom=validChars + '+';
    var word="(" + atom + "|" + quotedUser + ")";
    var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
    var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
    var matchArray=s.match(emailPat);

    if (matchArray==null) {
        return false;
    }

    var user=matchArray[1];
    var domain=matchArray[2];

    for (i=0; i<user.length; i++) {
        if (user.charCodeAt(i)>127) {
            return false;
       }
    }

    for (i=0; i<domain.length; i++) {
        if (domain.charCodeAt(i)>127) {
            return false;
       }
    }

    if (user.match(userPat)==null) {
        return false;
    }

    var IPArray=domain.match(ipDomainPat);
    if (IPArray!=null) {

        for (var i=1;i<=4;i++) {
            if (IPArray[i]>255) {
                return false;
           }
        }
        return true;
    }

    var atomPat=new RegExp("^" + atom + "$");
    var domArr=domain.split(".");
    var len=domArr.length;

    for (i=0;i<len;i++) {
        if (domArr[i].search(atomPat)==-1) {
            return false;
       }
    }

    if (checkTLD && domArr[domArr.length-1].length!=2 &&
            domArr[domArr.length-1].search(knownDomsPat)==-1) {
        return false;
    }

    if (len<2) {
        return false;
    }

    return true;
}


function checkField(field, fieldName, options)
{
    if (options & V_NOT_BLANK)
    {
        if (isBlank(field.value))
        {
            alert("The " + fieldName + " field may not be left blank.");
            field.focus();
            if ((field.type == "text") || (field.type == "textarea"))
                field.select();

            return false;
        }
    }

    if (options & V_HTML_SAFE)
    {
        if (!isHTMLSafe(field.value))
        {
            alert("The " + fieldName + " field contains illegal characters.\n\n" +
                "Illegal characters are:\n\n" +
                "Double quote: \"\nLess than sign: <\nGreater than sign: >");
            field.focus();
            if ((field.type == "text") || (field.type == "textarea"))
                field.select();

            return false;
        }
    }

    if (options & V_IS_DATE)
    {
        if (!isDate(field.value))
        {
            alert("The " + fieldName + " field must be in standard date format: mm/dd/yy.");
            field.focus();
            if ((field.type == "text") || (field.type == "textarea"))
                field.select();

            return false;
        }
    }

    if (options & V_IS_TIME)
    {
        if (!isTime(field.value))
        {
            alert("The " + fieldName + " field must be in standard time format. For example:\n\n1:12\n-OR-\n1:12:05 (with seconds)\n\n- Military time is not allowed\n- AM/PM suffix not allowed in this box");
            field.focus();
            if ((field.type == "text") || (field.type == "textarea"))
                field.select();

            return false;
        }
    }

    if (options & V_IS_NUMBER)
    {
        n = field.value;

        if (n.charAt(0) == '$')
        {
            n = n.substr(1);
        }

        if (n.charAt(n.length - 1) == '%')
        {
            n = n.substr(0, n.length - 2);
        }

        n = n.replace(/\,/g, "");

        if (isNaN(n))
        {
            alert("The " + fieldName + " field must be a number.");
            field.focus();
            if ((field.type == "text") || (field.type == "textarea"))
                field.select();

            return false;
        }
    }

    if (options & V_IS_EMAIL)
    {
        if (!isEmail(field.value))
        {
            alert("The " + fieldName + " field must contain a valid email address.\n\nExample: you@yourdomain.com");
            field.focus();
            if ((field.type == "text") || (field.type == "textarea"))
                field.select();

            return false;
        }
    }

    return true;
}


function countWords(s)
{
    s = s.replace(/[\f\n\r\t\v]/g, " ");
    s = s.replace(/ +/g, " ");
    s = trim(s);

    if (s.length > 0)
        return s.split(" ").length;
    else
        return 0;
}


var savedFieldValues = new Array();


function saveFieldValue(e)
{
    var saveme;

    if ((e.type == "text") || (e.type == "textarea"))
    {
        saveme = e.value;
    }
    else if (e.type == "select-one")
    {
        saveme = e.selectedIndex;
    }
    else if (e.type == "checkbox")
    {
        saveme = e.checked;
    }
    else
    {
        saveme = "";
    }

    if (typeof(savedFieldValues[e.form.name]) == "undefined")
    {
        savedFieldValues[e.form.name] = new Array();
    }

    savedFieldValues[e.form.name][e.name] = saveme;
}


function loadFieldValue(e)
{
    if (typeof(savedFieldValues[e.form.name][e.name]) != "undefined")
    {
        if ((e.type == "text") || (e.type == "textarea"))
        {
            e.value = savedFieldValues[e.form.name][e.name];
        }
        else if (e.type == "select-one")
        {
            e.options[savedFieldValues[e.form.name][e.name]].selected = true;
        }
        else if (e.type == "checkbox")
        {
            e.checked = savedFieldValues[e.form.name][e.name];
        }
    }
}


function setFieldBlank(e)
{
    if ((e.type == "text") || (e.type == "textarea"))
    {
        e.value = "";
    }
    else if (e.type == "select-one")
    {
        for (var i = 0; i < e.options.length; i++)
        {
            if (e.options[i].value == "")
            {
                e.options[i].selected = true;
                break;
            }
        }
    }
    else if (e.type == "checkbox")
    {
        e.checked = false;
    }
}


function toggleDisable(e, doDisable, saveValue)
{
    if (typeof(e) != "undefined")
    {
        if (doDisable && !e.disabled)
        {
            e.disabled = true;
            e.style.background = "#ddd";

            if (saveValue)
            {
                saveFieldValue(e);
            }

            setFieldBlank(e);
        }
        else if (!doDisable && e.disabled)
        {
            e.disabled = false;
            e.style.background = "#fff";
            loadFieldValue(e);
        }
    }
}