// fuck the leap year
var monthDays = new Array(31,28,31,30,31,30,31,31,30,31,30,31);

function isValidState(state) {
    var theState = state.toUpperCase();
    return (theState == 'AK' || theState == 'AL' || theState == 'AR' ||
            theState == 'AZ' || theState == 'CA' || theState == 'CO' ||
            theState == 'CT' || theState == 'DC' || theState == 'DE' ||
            theState == 'FL' || theState == 'GA' || theState == 'HI' ||
            theState == 'IA' || theState == 'ID' || theState == 'IL' ||
            theState == 'IN' || theState == 'KS' || theState == 'KY' ||
            theState == 'LA' || theState == 'MA' || theState == 'MD' ||
            theState == 'ME' || theState == 'MI' || theState == 'MN' ||
            theState == 'MO' || theState == 'MS' || theState == 'MT' ||
            theState == 'NC' || theState == 'ND' || theState == 'NE' ||
            theState == 'NH' || theState == 'NJ' || theState == 'NM' ||
            theState == 'NV' || theState == 'NY' || theState == 'OH' ||
            theState == 'OK' || theState == 'OR' || theState == 'PA' ||
            theState == 'RI' || theState == 'SC' || theState == 'SD' ||
            theState == 'TN' || theState == 'TX' || theState == 'UT' ||
            theState == 'VA' || theState == 'VT' || theState == 'WA' ||
            theState == 'WI' || theState == 'WV' || theState == 'WY');
}

function isNumeric(str) {
    var i = 0;
    var valid = true;
    var len = str.length;
    for (i = 0; i < len && valid; i++) {
        if (!isDigit(str.charAt(i))) {
            valid = false;
        }
    }
    return valid;
}

// number must be in form n.nn
// At least one digit before the . and only two digits after the .
// no negative sign
// all digits (plus one .)
function isValidDecimalAmount(str) {
    var hasDecimal = false;
    var digitsAfterDecimal = 0;
    var digitsBeforeDecimal = 0;
    var i = 0;
    var len = str.length;
    var valid = true;

    for (i = 0; i < len && valid; i++) {
        if (str.charAt(i) == '.') {
            if (hasDecimal) {
                valid = false;
            }
            else {
                hasDecimal = true;
            }
        }
        else if (!isDigit(str.charAt(i))) {
            valid = false;
        }
        else if (!hasDecimal) {
            digitsBeforeDecimal++;
        }
        else {
            digitsAfterDecimal++;
        }
    }

    if (valid) {
        if (digitsBeforeDecimal == 0 ||
            digitsAfterDecimal != 2 ||
            !hasDecimal) {
            valid = false;
        }
    }

    return valid;
}

function isDigit(ch) {
    return (ch >= '0' && ch <= '9');
}

function isValidEmailAddress(email) {
    if (email.indexOf(' ') >= 0 ||
        email.indexOf('(') >= 0 ||
        email.indexOf('(') >= 0 ||
        email.indexOf('<') >= 0 ||
        email.indexOf('>') >= 0 ||
        email.indexOf(';') >= 0 ||
        email.indexOf(':') >= 0 ||
        email.indexOf(',') >= 0) {
        return false;
    }
    var atIdx = email.indexOf('@');
    var dotIdx = email.lastIndexOf('.');
    // The last period must be at least 2 characters after the @ 
    // If this condition fails, then the email address is ok
    return (!(atIdx < 1 || ((atIdx + 2) > dotIdx)));
}

function isValidCreditCard(cc) {
    if (cc == '4111111111111111') {
        return false;
    }
    var cardLength = cc.length;
    if (cardLength < 13 || !isNumeric(cc)) {
        return false;   
    }

    var total = 0;
    var modFlag = 0;
    var i = 0;
    var digits = 0;

    // Note the ASCII offset for a character digit is 48 higher 
    // than its numerical equivalent, so subtracting 48 from the 
    // ASCII value gives that character as a digit
    for (i = (cardLength - 1); i >= 0; i--) {
        if (modFlag == 1) {
            digits = (cc.charCodeAt(i) - 48) * 2;
            if (digits > 9) {
                digits -= 9;
            }
            total += digits;
            modFlag = 0;
        } 
        else {
            total += (cc.charCodeAt(i) - 48);
            modFlag = 1;
        }
    }

    return ((total % 10) == 0);
}

function isValidCCExtraDigits(cc, extradigits) {
    if (cc.charAt(0) == '5' || cc.charAt(0) == '4') {
        return (extradigits.length == 3 && isNumeric(extradigits));
    }
    else {
        return true;
    }
}

function isValidExpiryDate(exp) {
    if (exp.length != 4) {
        return false;
    }
    else if (!isNumeric(exp)) {
        return false;
    }

    var m = exp.substring(0, 2);
    var y = exp.substring(2, 4);
    var month = parseInt('1' + m) - 100;
    var year = parseInt('1' + y) - 100;
    var full_year = 0;
    if (year < 90) {
        full_year = 2000 + year;
    }
    else {
        full_year = 1900 + year;
    }

    var today = new Date();
    var expiry = new Date();

    expiry.setFullYear(full_year);
    expiry.setMonth(month - 1);
    expiry.setDate(monthDays[month - 1]);
    return (expiry.getTime() > today.getTime());
}

function isInvalidAreaCode(npa) {
    return (npa == '800' || npa == '888' || npa == '877' || npa == '866' || npa == '700' || npa == '900');
}

function isUnserviceableAreaCode(npa) {
    return false;
    // return (npa == '602' || npa == '928' || npa == '480' || npa == '623' || npa == '520');
}

function isValidBrwName(brwname) {
    var ok = true;
    for (var i = 0; i < brwname.length && ok; i++) {
        var c = brwname.charAt(i);
        if (!((c >= 'a' && c <= 'z') ||
              (c >= '0' && c <= '9') ||
              (c >= 'A' && c <= 'Z') ||
              c == '_')) {
            ok = false;
        }
    }
    return ok;
}
