﻿/*
* CreditCard Validator with QSP, Inc. specific enhancements
* Ported from http://www.braemoor.co.uk/software/creditcard.shtml by John Gardner
* Derived from http://www.ihwy.com/labs/jquery-validate-credit-card-extension.aspx by Jack Killpatrick
*
* Author: Matthew Sause
* Version 1.0.0 (3/15/2010)
*
* History:
* Card prefixes based on data at: http://en.wikipedia.org/wiki/Credit_card_number
* Added support for LaserCard
* Added QSP Test CC Number
*
* Dual licensed under the MIT and GPL licenses:
*   http://www.opensource.org/licenses/mit-license.php
*   http://www.gnu.org/licenses/gpl.html
*/
function validateCC(ccNumber) {
    //Create array of all accepted card types
    var cards = new Array();
    cards.push({ cardName: "Visa", lengths: "13,16", prefixes: "4", checkdigit: true });
    cards.push({ cardName: "MasterCard", lengths: "16", prefixes: "51,52,53,54,55", checkdigit: true });
    cards.push({ cardName: "AmEx", lengths: "15", prefixes: "34,37", checkdigit: true });
    cards.push({ cardName: "Discover", lengths: "16", prefixes: "6011,622,64,65", checkdigit: true });
    cards.push({ cardName: "QSPTest", lengths: "18", prefixes: "111222333444555666", checkdigit: false });
    cards.push({ cardName: "PrepSportswear", lengths: "18", prefixes: "999888777666555444", checkdigit: false });
    cards.push({ cardName: "CCLoadTest", lengths: "19", prefixes: "1000000097531246801", checkdigit: false });
    //	cards.push({ cardName: "DinersClub", lengths: "14,16", prefixes: "305,36,38,54,55", checkdigit: true });
    //	cards.push({ cardName: "CarteBlanche", lengths: "14", prefixes: "300,301,302,303,304,305", checkdigit: true });
    //	cards.push({ cardName: "JCB", lengths: "16", prefixes: "35", checkdigit: true });
    //	cards.push({ cardName: "enRoute", lengths: "15", prefixes: "2014,2149", checkdigit: true });
    //	cards.push({ cardName: "Solo", lengths: "16,18,19", prefixes: "6334,6767", checkdigit: true });
    //	cards.push({ cardName: "Switch", lengths: "16,18,19", prefixes: "4903,4905,4911,4936,564182,633110,6333,6759", checkdigit: true });
    //	cards.push({ cardName: "Maestro", lengths: "12,13,14,15,16,18,19", prefixes: "5018,5020,5038,6304,6759,6761", checkdigit: true });
    //	cards.push({ cardName: "VisaElectron", lengths: "16", prefixes: "417500,4917,4913,4508,4844", checkdigit: true });
    //	cards.push({ cardName: "LaserCard", lengths: "16,17,18,19", prefixes: "6304,6706,6771,6709", checkdigit: false });

    //Ensure it's only digits, spaces, and dashes
    var cardexp = /^[\d\s\-]+$/;
    if (!cardexp.exec(ccNumber)) return false;

    ccNumber = ccNumber.replace(/\D/g, ""); // strip down to digits
    var cardexp = /^[0-9]{13,19}$/; //Ensure it's between 13 and 19 digits
    if (!cardexp.exec(ccNumber)) return false; // Has chars or wrong length

    //Check for valid Checkdigit
    var checkdigitValid = false;
    var checksum = 0;
    var mychar = "";
    var j = 1;
    var calc;
    for (var i = ccNumber.length - 1; i >= 0; i--) {
        calc = Number(ccNumber.charAt(i)) * j;
        if (calc > 9) {
            checksum++;
            calc += -10;
        }
        checksum += calc;
        if (j == 1) { j = 2 } else { j = 1 };
    }
    checkdigitValid = (checksum % 10 == 0);

    //For each credit card type check Prefix & Length Lists
    var prefixValid = false;
    var prefix = new Array();
    var lengthValid = false;
    var lengths = new Array();
    for (var x = 0; x < cards.length; x++) {
        //Check Prefix Is included in list
        prefixValid = false;
        prefix = cards[x].prefixes.split(",");
        for (var i = 0; i < prefix.length; i++) {
            var exp = new RegExp("^" + prefix[i]);
            if (exp.test(ccNumber)) {
                prefixValid = true;
                break;
            }
        }

        //Check Length Is included in list
        lengthValid = false;
        lengths = cards[x].lengths.split(",");
        for (var k = 0; k < lengths.length; k++) {
            if (ccNumber.length == lengths[k]) {
                lengthValid = true;
                break;
            }
        }

        //If it passed all 3 tests, return true
        if ((!cards[x].checkdigit || checkdigitValid) && prefixValid && lengthValid) return true;
    }
    return false; // Didn't pass all checks for a single card type
}


$(document).ready(function() {
    $('input.SMTP').blur(function(index) {
        validateSMTP(this, undefined);
    });

    //Run Validations in case there are pre-loaded Email Addresses
    var ArrQueue = [];
    var ArrElements = $('input.SMTP').toArray();
    while (ArrElements.length > 0) {
        ArrQueue.push(ArrElements.shift());
        if (ArrQueue.length >= 4){validateSMTP(ArrQueue); ArrQueue = [];}
    }
    validateSMTP(ArrQueue);
});


function validateSMTP(ArrElements, ArrTimeouts) {
    var addressElements = $.isArray(ArrElements) ? ArrElements : [ArrElements];
    var arrTimeoutList = ArrTimeouts || [2000, 4000, 5000];
    var thisTimeOut = arrTimeoutList.shift();
    var postData = '';
    if (addressElements.length === 0) return;
    for (var x = 0; x < addressElements.length; x++) {
        var el = addressElements[x];
        if (el == null || el.getAttribute('data-lastvalidated') == el.value) {
            addressElements.splice(x--, 1);
            continue;
        }
        if (el.value.length > 0) {
            postData += "&EmailAddress=" + encodeURIComponent(el.value);
            if (el.style.paddingRight != '24px') { el.style.paddingRight = '24px'; $(el).width($(el).width() - 24); }
            el.style.backgroundAttachment = 'scroll';
            el.style.backgroundRepeat = 'no-repeat';
            el.style.backgroundPosition = 'right center';
            el.style.backgroundImage = 'url(/common/images/ajax-loading.gif)';
            el.setAttribute('title', 'Checking Email Address');
        } else {
            addressElements.splice(x, 1);
            el.style.backgroundImage = 'none';
            el.setAttribute('title', '');
            el.setAttribute('data-lastvalidated', el.value);
        }
    }

    if (postData.length > 0) {
        postData = 'timeout=' + (thisTimeOut-100) + postData;
        $.ajax({
            async: true,
            timeout: thisTimeOut,
            type: "POST",
            url: "/email/validationservice.asmx/ValidateEmails",
            data: postData,
            dataType: "xml",
            success: function(xml) {
                var arrBrokenElements = [];
                $(xml).find('Validation').each(function() {
                    var el = addressElements[$(this).index()];
                    el.setAttribute('data-lastvalidated', el.value);
                    var ConfidenceLevel = parseInt($(this).find('ConfidenceLevel').text());
                    var Message = $(this).find('Message').text(); //.replace(/\'/g,'\\\'')
                    var imgSrc = '';
                    switch (ConfidenceLevel) {
                        case 0: imgSrc = 'status-bad.gif'; break;
                        case 1: imgSrc = 'status-bad.gif'; break;
                        case 2: imgSrc = 'status-bad.gif'; arrBrokenElements.push(el); break;
                        case 3: imgSrc = 'status-unknown.gif'; arrBrokenElements.push(el); break;
                        case 4: imgSrc = 'status-ok.gif'; break;
                        case 408: imgSrc = 'status-ok.gif'; arrBrokenElements.push(el); break;
                    }
                    //only show icon if we pass regex test
                    el.style.backgroundImage = 'none';
                    el.setAttribute('title', '');
                    if (ConfidenceLevel > 0) {
                        el.style.backgroundImage = 'url(/common/images/' + imgSrc + ')';
                        el.setAttribute('title', Message);
                    }
                });
                if (arrTimeoutList.length > 0 && arrBrokenElements.length > 0) {
                    $(arrBrokenElements).each(function(index) { this.setAttribute('data-lastvalidated', ''); });
                    validateSMTP(arrBrokenElements, arrTimeoutList);
                }
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                if (textStatus == "timeout" && arrTimeoutList.length > 0 && addressElements.length > 0) {
                    //timed out, try again with the next timeout from the list.
                    validateSMTP(addressElements, arrTimeoutList);
                } else {
                    //timed out too many times, bad response from server, or unknown transport error - mark email as OK.
                    for (var x = 0; x < addressElements.length; x++) {
                        var el = addressElements[x];
                        el.style.backgroundImage = 'url(/common/images/status-ok.gif)';
                        el.setAttribute('title', 'This email address is OK!');
                    }
                }
            }
        });
    }
}

