if (typeof String.prototype.ElfCheck !== 'function') {
    //validates dutch bank account numbers (except ING) usign the 11-check.
    String.prototype.ElfCheck = function () {
        var arr = this.replace(/\D/g, '').split('');
        var result = 0;
        if (arr.length == 9) { arr.splice(0, 0, 0) }
        for (var z = 0; z < arr.length; z++) {
            result += (arr[z] * (z * 1 + 1));
        }
        result = (result / 11);
        return (Math.floor(result) == result);
    };
}

if (typeof String.prototype.padZero !== 'function') {
    //pads the number to the specified length/
    //useful for dates etc. where a fixed length is required: 02 vs 2.
    String.prototype.padZero = function (length) {
        if (undefined == length || isNaN(length)) { return this; }
        var returnvar = this.toString();
        while (returnvar.length < length) {
            returnvar = '0' + returnvar;
        }
        return returnvar;
    };
}

if (typeof Date.prototype.isValid !== 'function') {
    //checks if date is valid.
    Date.prototype.isValid = function () {
        var d = this.getDate();
        var m = this.getMonth();
        var y = this.getFullYear();
        if (d > 30) {
            if (m == 1 || m == 3 || m == 5 || m == 8 || m == 10) {
                return false;
            } else if (d < 32) {
                return true;
            }
        } else if (m == 1 && d == 29) {
            if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
                return true;
            }
        } else if (m == 1 && d > 29) {
            return false;
        } else {
            return true;
        }
        return false;
    };
}

function createNewValidDate(y, m, d) {
    if (d > 30) {
        if (m == 1 || m == 3 || m == 5 || m == 8 || m == 10) {
            return [false, 'invalid: d > 30 for m ' + (m+1)];
        } else if (d < 32) {
            return [true, new Date(y,m,d)];
        }
    } else if (m == 1 && d == 29) {
        if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) {
            return [true, new Date(y,m,d)];
        } else {
            return [false, 'invalid: ' + y + ' is no leap year'];
        }
    } else if (m == 1 && d > 29) {
        return [false, 'invalid: d > 28 for m 2'];
    } else {
        return [true, new Date(y, m, d)];
    }
    return [false, ''];
}

function ArrayDiff(array1, array2) {
    //This function takes an array as argument
    //goal:     return the differences between the two arrays.
    //note:     make sure array is unique.
    //remarks:  alters original arrays. To prvent this, call this function with array.slice();
    if (!array1 || undefined == array1) {
        return array2;
    } else if (!array2 || undefined == array2) {
        return array1;
    }
    var result = [];
    var b = false; //boolean indicator: turns true if a match is found.
    if (array1.length < array2.length) {
        var temp = array1;
        array1 = array2;
        array2 = temp;
    }
    var i = 0;
    while (i < array1.length) {
        b = false;
        var j = 0;
        while (j < array2.length) {
            if (array1[i] == array2[j]) {
                array2.splice(j, 1); //remove the item from array2.
                b = true;
                break;
            } else {
                b = false;
            }
            j++;
        }
        if (!b) {
            result.push(array1[i]);
        }
        i++;
    }
    return result.concat(array2);
}

if (typeof String.prototype.trim !== 'function') {
    String.prototype.trim = function () {
        return this.replace(/^\s+|\s+$/, '');
    };
}


//maakt een array uniek, dubbele waardes worden weggegooid
function ArrayUnique(ar1) {
    var a = [];
    var l = ar1.length;
    for (var i = 0; i < l; i++) {
        for (var j = i + 1; j < l; j++) {
            // If this[i] is found later in the array
            if (ar1[i] === ar1[j]) {
                j = i + 1;
                i = i + 1;
            }
        }
        a.push(ar1[i]);
    }
    return a;
};


function message(element, success, show, newtext, newheader) {
    element = (element) ? $(element) : $('#error');

    if (!show && !newtext && !newheader) {
        
        if (!success.IsError) { return false; };
        var newtext = success.ErrorMessage;
        var success = success.Type;
        var show = true;
        var newheader;
    }
    if (!success || success == 4) {
        element.addClass('error');
        newheader = "Fout";
    } else if (success == 3) {
        newheader = 'Waarschuwing';
        element.addClass('warning');
    } else if (success == 2) {
        newheader = "Let op";
        element.addClass('info');
    } else if (success == 1) {
        newheader = "Gelukt";
        element.addClass('success');
    } else {
        newheader = "Fout";
        element.addClass('error');
    }

    element.hide();
    element.removeClass('error');
    element.removeClass('success');

    if (newtext && newheader) {
        element.find('.errorcontent').html('<h2 style="margin-top: -8px; margin-bottom: -5px;">' + newheader + '</h2><p>' + newtext + '</p>');
    } else if (newtext && !newheader) {
        element.find('.errorcontent').html(newtext);
    }

    if (!show) {
        return false;
    }

    

    element.find('.close').bind('click', function (event) {
        element.slideUp('slow');
        event.preventDefault();
    });

    element.fadeIn('slow');
}

function validation(testvalue, type, optional) {
    //returns true if valid
    
    var rege = /.*/i;

    if (!testvalue || testvalue == '' || undefined == testvalue || testvalue == -1) {
        if (!optional || undefined == optional || 'false' == optional) {
            return false;
        } else {
            return true;
        }
    }

    switch (type) {
        case 'email':
            //email address validation.
            rege = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
            break;
        case 'name':
            //rege = /^[a-z.-]{1,}$/i;
            //rege = /^(\s|\w|[-_.])+$/i;
            break;
        case 'lastname':
            //rege = /^[a-z.-]{1,}$/i;
            //rege = /^(\s|[a-zA-Z-])+$/i;
            break;
        case 'address':
            rege = /^(\d|\s|\w|[-_])+$/i;
            break;
        case 'tel':
            //dutch telnr: 10 digits starting with a zero.
            rege = /^0\d{9}$/i;
            break;
        case 'int_tel':
            //int telnr: + and 11 digits.
            rege = /^\+\d{6,11}$/i;
            break;
        case 'initials':
            //Initials A.B. etc
            rege = /^([a-z][.])+$/i;
            break;
        case 'cell':
            //dutch cellular number: 06xxxxxxxx
            rege = /^06\d{8}$/i;
            break;
        case 'date':
            //full date: DD-MM-YYYY or D-M-YYYY
            rege = /^((0?[1-9]|[12][0-9]|3[01])[-](0?[1-9]|1[012])[-](?:19|20)\d{2})$/i;
            break;
        case 'dob':
            //full date: DD-MM-YYYY or D-M-YYYY
            rege = /^((0?[1-9]|[12][0-9]|3[01])[-](0?[1-9]|1[012])[-]19\d{2})$/i;
            break;
        case 'day':
            rege = /^(0?[1-9]|[12][0-9]|3[01])$/i;
            break;
        case 'month':
            rege = /^(0?[1-9]|1[012])$/i;
            break;
        case 'year':
            //19 or 20 with 2 digits following.
            rege = /^(?:19|20)\d{2}$/i;
            break;
        case 'dob_year':
            //19 with 2 digits
            rege = /^19\d{2}/i;
            break;
        case 'zip':
            //NL zipcode
            rege = /^\d{4}\s?[a-z]{2}$/i;
            break;
        case 'num':
            //nummeric only
            rege = /^\d+$/i;
            break;
        case 'CVV':
            //for use with credit card CVV validation code.
            rege = /^\d{3}$/i;
            break;
        case 'CCN':
            //for use with credit card number.
            rege = /^\d{16}$/i;
            break;
        case 'kvk':
            //KVK nummers valideren
            rege = /^\d{2,14}$/i;
            break;
        case 'ID':
            //for use with dutch ID
            rege = /^\w{8,12}$/i;
            break;
        case 'bankaccount':
            rege = /^\d+$/i;
            break;
        case 'password':
            rege = /^[a-zA-Z0-9]{8,}$/i;
            break;
        case 'none':
            return true;
            break;
        case 'select':
            rege = /^[^-].*$/i;
            break;
        case 'checkbox':
            rege = /^selected/gi;
            break;
        case 'iccid':
            rege = /^\d{8,20}$/i;
            break;
        case 'currency':
            rege = /^\d+[.,]?(\d{2})?$/i;
            break;
        case 'alphanumeric':
            rege = /^(\d|\w){8}$/i
            break;
        case 'nl_bankaccount':
            if (blockedaccountlist.indexOf(testvalue.toString()) > -1) {
                return false;
            } else {
                switch (testvalue.length) {
                    case 9:
                    case 10:
                        rege = /^\d{9,10}$/i;
                        return rege.test(testvalue) && testvalue.ElfCheck();
                        break;
                    case 8:
                        return false;
                        break;
                    default:
                        rege = /^\d{5,7}$/i;
                        break;
                }
            }
            break;
        case 'multiline':
            //rege = /^[^<>]+$/i;
            break;
        default:
           // rege = /^([a-zA-Z0-9-_.,:?!]|\s)+$/i;
            break;
    }
    return rege.test(testvalue);
}

function ValidateThis(element) {
    $(element).each(function () {
        if (validation($(this).val(), $(this).data('validation'), $(this).data('optional'))) {
            Valid($(this));
        } else {
            inValid($(this));
        }
    });
}

function ValidateInitialize(element) {
    $(element).each(function () {
        var ele = $(this);
        if ($(this).is('input[type=checkbox]')) {
            ele = $(this).parent('span');
        }

        $(this).data('validation', ele.attr('validation'));
        $(this).data('optional', ele.attr('optional'));
        $(this).data('validationname', ele.attr('validationname'));
        $(this).bind('change', function () {
            ValidateThis($(this));
        });
        $(this).bind('keyup', function () {
            if (ele.is('.invalid')) {
                ValidateThis(ele);
            }
        });
        ele.removeAttr('validation');
        ele.removeAttr('optional');
        ele.removeAttr('validationname');
    });
}

function ValidateAll(element) {
    var counter = 0;
    var invalids = '';
    $(element).not(function () { return $(this).closest('tr').is('.hidden') }).each(function () {
        if ($(this).is('input[type=text], input[type=password], textarea') && (!$(this).val() == '' || $(this).filter('input[type=text], input[type=password], textarea').data('optional') == 'true')) {
            if (validation($(this).val(), $(this).data('validation'), $(this).data('optional'))) {
                counter++;
                Valid($(this));
            } else {
                inValid($(this));
                if (($(this).data('validation') == 'tel' || $(this).data('validation') == 'cell') && !$(this).data('optional') && $(this).val().length < 10) {
                    invalids += '<li> Een mobiel nummer dient uit 10 cijfers te bestaan.</li>';
                } else if ($(this).data('validation') == 'CCN' && !$(this).data('optional') && $(this).val().length < 13) {
                    invalids += '<li> Het creditcard nummer is niet correct.</li>';
                } else {
                    invalids += '<li>' + $(this).data('validationname') + '</li>';
                }
            }
        } else if ($(this).is(':checked') || ($(this).is(':checkbox') && $(this).data('optional') == 'true')) {
            counter++;
            Valid($(this));
        } else if (!$(this).is(':checked') && $(this).is(':checkbox') && $(this).data('optional') != 'true') {
            invalids += '<li>' + $(this).data('validationname') + ' is verplicht</li>';
            inValid($(this));
        } else if ($(this).is('select')) {
            if (validation($(this).find('option:selected').val(), $(this).data('validation'), $(this).data('optional')) || $(this).data('optional') == 'true') {
                counter++;
                Valid($(this));
            } else {
                invalids += '<li>' + $(this).data('validationname') + '</li>';
            }
        } else {
            invalids += '<li>' + $(this).data('validationname') + '</li>';
            inValid($(this));
        }
    });

    if (counter == $(element).not(function () { return $(this).closest('tr').is('.hidden'); }).length) {
        return true;
    }
    return invalids;
}

function Valid(element) {
    $(element).addClass('valid').removeClass('invalid');
    $(element).closest('td').addClass('valid').removeClass('invalid');
}
function inValid(element) {
    $(element).addClass('invalid').removeClass('valid');
     $(element).closest('td').addClass('invalid').removeClass('valid');
}

function doValidateAll(checkelement, statusboxel) {
    var valid = ValidateAll(checkelement);
    statusboxel = (statusboxel) ? $(statusboxel) : $('#error');
    if (valid === true) {
        return true;
    }
    message(statusboxel, false, true, '<p>De volgende velden zijn niet (goed) ingevuld:</p><ul>' + valid + '</ul>');
    return false;
}

function validateRadio(element) {
    var total = [];
    var select = [];
    $(element).find('input[type=radio]').bind('change', function () {
        validateRadio(element);
    });
    $(element).find('input[type=radio]').filter(':visible').each(function () {
        total.push($(this).attr('name'));
    });
    $(element).find('input[type=radio]').filter(':visible').filter(':checked').each(function () {
        select.push($(this).attr('name'));
    });
    var diff = ArrayDiff(ArrayUnique(select), ArrayUnique(total));
    //var diff = select.unique().diff(total.unique());
    Valid($(element).find('input[type=radio]').parent());
    if (diff.length > 0) {
        var x = 0;
        //$.browser.msie && $.browser.version < 9
        $('input[type=radio]').each(function (index, radiobtn) {
            if (!$(radiobtn).is('.' + $(radiobtn).attr('name').replace(/\W/gi, ''))) {
                $(radiobtn).addClass($(radiobtn).attr('name').replace(/\W/gi, ''));
            }
        });
        while (x < diff.length) {
            inValid($('.' + diff[x].replace(/\W/gi, '') + '').parent());
            x++;
        }
        while (x < diff.length) {
            inValid($('input[name=' + diff[x] + ']').parent());
            x++;
        }
        return false;
    }
    return true;
}

function validateDate(element, year, modifier) {
    var yearyear = (year) ? year : 0;
    var today = new Date();
    var dates = true;

    $(element).each(function (ind, tr) {
        if ($(tr).find('input').length == 3) {
            var datetemp = '';
            $(tr).find('input').each(function (index, input) {
                datetemp += $(this).val();
            });
            var testdate = new Date(datetemp.substr(4, 4), datetemp.substr(2, 2), datetemp.substr(0, 2));
            today.setFullYear(today.getFullYear() + year);
            var tmp = (modifier == 'gte') ? today >= testdate : today <= testdate;

            if (tmp && testdate.isValid()) {
                dates = dates && true;
            } else {
                inValid($(tr).find('input'));
                dates = dates && false                
                if (year == 18 && modifier == 'gte') {                    
                    message($('#error'), false, true, 'Je bent nog geen 18 jaar oud.');
                } else if (year == 0 && modifier == 'lte') {
                    message($('#error'), false, true, 'Startdatum dient in de toekomst te liggen');
                }
            }
        }
    });
    return dates;
}


