var CreditCardNumberValidation = {

    // "Public" functions:

    Generic: function (sCardNumber) {
        return this._Test(/^\d{12,19}$/, sCardNumber);
    },

    Amex: function (sCardNumber) {
        return this._Test(/^3[47]\d{13}$/, sCardNumber);
    },

    DinersClub: function (sCardNumber) {
        return this._Test(/^(30[0-5]|36\d|38\d)\d{11}$/, sCardNumber);
    },

    Discover: function (sCardNumber) {
        return this._Test(/^6011\d{12}$/, sCardNumber);
    },

    JCB: function (sCardNumber) {
        //return this._Test(/^35((28)|(89))\d{12}$/, sCardNumber);
        return this._Test(/^(?:2131|1800|35\d{3})\d{11}$/, sCardNumber);
    },

    MasterCard: function (sCardNumber) {
        return this._Test(/^5[1-5]\d{14}$/, sCardNumber);
    },

    Solo: function (sCardNumber) {
        return this._Test(/^((6334)|(6767))\d{12}(\d{2,3})?$/, sCardNumber);
    },

    Visa: function (sCardNumber) {
        return this._Test(/^4\d{12}(\d{3})?$/, sCardNumber);
    },

    // "Private" functions:

    _Test: function (oRegex, sCardNumber) {

        // Strip any non-digits (useful for credit card numbers with spaces and hyphens)
        sCardNumber = sCardNumber.replace(/\D/g, '');

        if (oRegex.test(sCardNumber)) {
            return this._LuhnAlgorithm(sCardNumber);
        }

        return false;
    },

    _LuhnAlgorithm: function (sCardNumber) {

        //Checks for parity in the card number:

        var bDouble = false;
        var iSum = 0, iNum;

        for (var i = sCardNumber.length - 1; i >= 0; i--) {

            iNum = parseInt(sCardNumber.charAt(i));

            if (bDouble) {
                iSum += (iNum > 4) ? (iNum * 2 - 9) : (iNum * 2);
            } else {
                iSum += iNum;
            }

            bDouble = !bDouble;
        }

        return (iSum % 10) == 0;
    }
}

function validateCardNumber_BW(sCardNumber, iSelectedValue) {
    switch (iSelectedValue) {
        case 1:  //MasterCard
            return CreditCardNumberValidation.MasterCard(sCardNumber);
        case 2:  //Visa
            return CreditCardNumberValidation.Visa(sCardNumber);
        case 3:  //American Express:
            return CreditCardNumberValidation.Amex(sCardNumber);
        case 4:  //Diners:
            return CreditCardNumberValidation.DinersClub(sCardNumber);
        default:
            return CreditCardNumberValidation.Generic(sCardNumber);
    }
}

function validateCardNumber_MR(sCardNumber, iSelectedValue) {

    switch (iSelectedValue) {
        case 161:  //Visa
        case 162:  //Visa Debit
        case 170:  //Visa Electron
            return CreditCardNumberValidation.Visa(sCardNumber);

        case 163:  //MasterCard
            return CreditCardNumberValidation.MasterCard(sCardNumber);

        case 164:  //American Express:
            return CreditCardNumberValidation.Amex(sCardNumber);

        case 167:  //Diners
            return CreditCardNumberValidation.DinersClub(sCardNumber);

        case 168:  //JCB
            return CreditCardNumberValidation.JCB(sCardNumber);

        case 169:  //SOLO
            return CreditCardNumberValidation.Solo(sCardNumber);

        default:
            return CreditCardNumberValidation.Generic(sCardNumber);
    }
}

function validateCardNumber_VO(sCardNumber, iSelectedValue) {

    switch (iSelectedValue) {
        case 1:  //Visa
            return CreditCardNumberValidation.Visa(sCardNumber);

        case 2:  //MasterCard
            return CreditCardNumberValidation.MasterCard(sCardNumber);

        case 3:  //American Express:
            return CreditCardNumberValidation.Amex(sCardNumber);

        default:
            return CreditCardNumberValidation.Generic(sCardNumber);
    }
}
