/* Minification failed. Returning unminified contents.
(215,48-49): run-time error JS1193: Expected ',' or ')': !
(215,51-52): run-time error JS1014: Invalid character: @
(215,52-53): run-time error JS1195: Expected expression: |
(215,57-58): run-time error JS1014: Invalid character: \
(215,57-58): run-time error JS1195: Expected expression: \
(215,58-90): run-time error JS1015: Unterminated string constant: '?#\$%\^\&*\)\(+=._\-,~]/))) {
(217,9-10): run-time error JS1002: Syntax error: }
(220,42-43): run-time error JS1004: Expected ';': {
(225,5-6): run-time error JS1002: Syntax error: }
(227,89-90): run-time error JS1004: Expected ';': {
(237,6-7): run-time error JS1195: Expected expression: )
(236,9-23): run-time error JS1018: 'return' statement outside of function: return isValid
(224,9-23): run-time error JS1018: 'return' statement outside of function: return isValid
 */
// By default, jquery validation ignores hidden fields, but sometimes we want to validate against the value in a hidden field
// It wont work inside of document ready or inside a function, so must be at the root of the file here.
$.validator.setDefaults({ ignore: null });

(function ($) {
    // See the corresponding Attribute class in the Validators folder of the Web Project
    //  for the IClientValidation implimentation, as well as the server side IsValid method.

    // Equals validator to compare two fields
    $.validator.unobtrusive.adapters.add("equals", ["other"],
        function (options) {
            options.rules['equals'] = {
                other: "#" + options.params.other // So that we can select the element in the function
            };
            options.messages['equals'] = options.message;
        }
    );
    $.validator.addMethod("equals", function (value, element, params) {

        var isValid = false;

        if (value === $(params.other).val())
            isValid = true;

        return isValid;
    });
    // Adding a new adapter to JQuery's unobtrusive validation
    $.validator.unobtrusive.adapters.add("address", [],
        function (options) {
            options.rules['address'] = {};
            options.messages['address'] = options.message;
        }
    );

    $.validator.addMethod("address", function (value, element, params) {
        var isValid = true;

        var pattern = /^ *((#\d+)|((box|bin)[-. \/\\]?\d+)|(.*p[ \.]? ?(o|0)[-. \/\\]? *-?((box|bin)|b|(#|num)?\d+))|(p(ost)? *(o(ff(ice)?)?)? *((box|bin)|b)? *\d+)|(p *-?\/?(o)? *-?box)|post office box|((box|bin)|b) *(number|num|#)? *\d+|(num|number|#) *\d+)/i;
        if (value.match(pattern)) {
            isValid = false;
        }

        return isValid;
    });
    $.validator.unobtrusive.adapters.add("unlikeif", ['unlikeproperty', 'iftrueproperty'],
        function (options) {
            options.rules['unlikeif'] = {
                unlikeproperty: options.params.unlikeproperty,
                iftrueproperty: options.params.iftrueproperty
            };
            options.messages['unlikeif'] = options.message;
        }
    );

    $.validator.addMethod("unlikeif", function (value, element, params) {
        var form = $(element).closest("form");

        var unlikeElement = $('input[id$="' + params.unlikeproperty + '"]', $(form));
        var ifTrueElement = $('input[id$="' + params.iftrueproperty + '"]', $(form));

        var isTrue =
            // If it's a textbox...
            $(ifTrueElement).val().toLowerCase() === "true" ||
            // OR: If it's a checkbox...
            ($(ifTrueElement).length > 0 && $(ifTrueElement)[0].checked);

        if (isTrue && unlikeElement.val().toLowerCase() === value.toLowerCase()) {
            return false;
        }

        return true;
    });
    // Sets a property required if a property on the same object is set to true or
    // is equal to the second value provided
    $.validator.unobtrusive.adapters.add("requiredif", ["otherpropertyname", "otherpropertyvalues"],
        function (options) {
            options.rules['requiredif'] = {
                otherpropertyname: options.params.otherpropertyname, // So that we can select the element in the function
                otherpropertyvalues: options.params.otherpropertyvalues
            };
            options.messages['requiredif'] = options.message;
        }
    );

    $.validator.addMethod("requiredif", function (value, element, params) {
        var isValid = true;
        var elementName = $(element).attr("name");
        var form = $(element).closest("form");

        var elementNameParts = elementName.split('.');
        var propertyNameIndex = elementNameParts.length - 1;

        var propertyName = elementNameParts[propertyNameIndex];

        var substringLength = elementName.length - propertyName.length;

        var elementPrefix = elementName.substring(0, substringLength);

        var otherElementSelector = "[name='" + elementPrefix + params.otherpropertyname + "']";

        var isRequired = true;
        if (typeof params.otherpropertyvalues !== "undefined" && params.otherpropertyvalues !== "") {
            isRequired = params.otherpropertyvalues.indexOf($(otherElementSelector, $(form)).val()) !== -1;
        } else {
            isRequired = $(otherElementSelector, $(form)).val() === "True" || $(otherElementSelector, $(form)).val() === "true";
        }

        if (Array.isArray(value)) {
            if (isRequired && value != null && value.length == 0)
                isValid = false;
        } else if (isRequired && value != null && value !== undefined && value.trim() === "")
            isValid = false;

        return isValid;
    });
    $.validator.unobtrusive.adapters.add("dobrange", [],
        function (options) {
            options.rules['dobrange'] = {};
            options.messages['dobrange'] = options.message;
        }
    );

    $.validator.addMethod("dobrange", function (value, element, params) {
        var isValid = true;

        var userDOB = new Date(value);
        var upperLimit = new Date();
        upperLimit.setFullYear(upperLimit.getFullYear() - 19);
        var lowerLimit = new Date();
        lowerLimit.setFullYear(lowerLimit.getFullYear() - 120);

        if (userDOB > upperLimit) {
            isValid = false;
        }

        if (isValid && (userDOB < lowerLimit)) {
            isValid = false;
        }

        return isValid;
    });

    $.validator.unobtrusive.adapters.add("strongpasswordcheck", [],
        function (options) {

            // These were defined for legibility
            var tooShortRule = 0;
            var tooLongRule = 1;
            var noWhiteSpaceRule = 2;
            var threeRulesNotMet = 3;
            var noUsernameInPasswordRule = 4;

            // This array contains error messages passed by C# within the GetClientValidationRules override, defined in the ModelClientValidationRule that is passed
            var multipleMessages = options.message.split(",");

            // A new rule must be added for each custom conditional validation check belonging to this adapter
            options.rules['tooShortRule'] = {};
            options.messages['tooShortRule'] = multipleMessages[tooShortRule];

            options.rules['tooLongRule'] = {};
            options.messages['tooLongRule'] = multipleMessages[tooLongRule];

            options.rules['noWhiteSpaceRule'] = {};
            options.messages['noWhiteSpaceRule'] = multipleMessages[noWhiteSpaceRule];

            options.rules['threeRulesNotMet'] = {};
            options.messages['threeRulesNotMet'] = multipleMessages[threeRulesNotMet];

            options.rules['noUsernameInPasswordRule'] = {};
            options.messages['noUsernameInPasswordRule'] = multipleMessages[noUsernameInPasswordRule];
        }
    );

    // These methods all correspond to the rules defined in the adapter (rules[tooShortRule], messages[tooShortRule])
    $.validator.addMethod("tooShortRule", function (value, element, params) {
        var isValid = true;
        if (value.length < 8) {
            isValid = false;
        }
        return isValid;
    });

    $.validator.addMethod("tooLongRule", function (value, element, params) {
        var isValid = true;
        if (value.length > 16) {
            isValid = false;
        }
        return isValid;
    });

    $.validator.addMethod("noWhiteSpaceRule", function (value, element, params) {
        var isValid = true;
        if (value.match(/\s+/)) {
            isValid = false;
        }
        return isValid;
    });

    $.validator.addMethod("threeRulesNotMet", function (value, element, params) {
        var isValid = true;
        var validCount = 0;

        if (isValid && (value.match(/[a-z]/))) {
            validCount++;
        }

        if (isValid && (value.match(/[A-Z]/))) {
            validCount++;
        }

        if (isValid && (value.match(/\d/))) {
            validCount++;
        }

        if (isValid && (value.match(/[`\\\[\]"/!{}@|<>:;\'?#\$%\^\&*\)\(+=._\-,~]/))) {
            validCount++;
        }

        // Must pass 3 out of 4 security requirements
        if (isValid && (validCount < 3)) {
            isValid = false;
        }

        return isValid;
    });

    $.validator.addMethod("noUsernameInPasswordRule", function (value, element, params) {
        var isValid = true;

        var studentId = $("#StudentId").val();

        if (studentId && value.indexOf(studentId) != -1) {
            isValid = false;
        }        
        
        return isValid;
    });

}(jQuery));;
