/* Minification failed. Returning unminified contents.
(141,55-63): run-time error JS1193: Expected ',' or ')': function
(141,65-66): run-time error JS1195: Expected expression: )
(141,67-68): run-time error JS1004: Expected ';': {
(143,45-55): run-time error JS1004: Expected ';': grecaptcha
(151,22-23): run-time error JS1195: Expected expression: )
(157,17-18): run-time error JS1002: Syntax error: }
(165,79-80): run-time error JS1195: Expected expression: )
(165,81-82): run-time error JS1004: Expected ';': {
(167,6-7): run-time error JS1195: Expected expression: )
(169,62-63): run-time error JS1195: Expected expression: )
(169,64-65): run-time error JS1004: Expected ';': {
(171,6-7): run-time error JS1195: Expected expression: )
(172,62-63): run-time error JS1195: Expected expression: )
(172,64-65): run-time error JS1004: Expected ';': {
(174,6-7): run-time error JS1195: Expected expression: )
(174,7-8): run-time error JS1197: Too many errors. The file might not be a JavaScript file: ;
(156,21-33): run-time error JS1018: 'return' statement outside of function: return false
 */
// Initialize "sessionTimedout" to false.  (When a session times out, this is set to "true" on the SessionTimeout.cshtml landing page.)
var sessionTimedout = false;
$(function () {
    PageSetup();
    // Show a loading symbol for all AJAX requests from the time the request is sent until the page is updated.
    var $loading = $('#loadingDiv').hide();
    $(document)
    .ajaxStart(function () {
        $loading.show();
    })
    .ajaxStop(function () {
        $loading.hide();
    });

    // This should only be "true" if the SessionTimeout.cshtml landing page just loaded (in between initializing the "sessionTimedout" variable above, and the below statement...)
    if (!sessionTimedout) {
        // ------------------------------ Session Timeout Warning -------------------------------- //
        var originalTitle = document.title;
        // StringHelpers Module
        // Call by using StringHelpers.padLeft("1", "000");
        var StringHelpers = function () {
            return {
                // Pad string using padMask.  string '1' with padMask '000' will produce '001'.
                padLeft: function (string, padMask) {
                    string = '' + string;
                    return (padMask.substr(0, (padMask.length - string.length)) + string);
                }
            };
        }();

        // SessionManager Module
        var SessionManager = function () {

            var sessionTimeoutSeconds = (serverSessionTimeout * 60),
                countdownSeconds = 5 * 60, // 5 minutes
                secondsBeforePrompt = sessionTimeoutSeconds - countdownSeconds,
                displayCountdownIntervalId,
                promptToExtendSessionTimeoutId,
                count = countdownSeconds,
                extendSessionUrl = $('#ExtendSessionURL').attr('href'),
                expireSessionUrl = $('#ExpireSessionURL').attr('href');// + '?returnUrl=' + location.pathname;

            var endSession = function () {
                $('#sm-countdown-dialog').modal('hide');
                location.href = expireSessionUrl;
            };

            var displayCountdown = function () {
                var countdown = function () {
                    var cd = new Date(count * 1000),
                        minutes = cd.getUTCMinutes(),
                        seconds = cd.getUTCSeconds(),
                        minutesDisplay = minutes === 1 ? '1 minute ' : minutes === 0 ? '' : minutes + ' minutes ',
                        secondsDisplay = seconds === 1 ? '1 second' : seconds + ' seconds',
                        cdDisplay = minutesDisplay + secondsDisplay;

                    document.title = 'Expire in ' +
                        StringHelpers.padLeft(minutes, '00') + ':' +
                        StringHelpers.padLeft(seconds, '00');
                    $('#sm-countdown').html(cdDisplay);
                    if (count === 0) {
                        document.title = 'Session Expired';
                        endSession();
                    }
                    count--;
                };
                countdown();
                displayCountdownIntervalId = window.setInterval(countdown, 1000);
            };

            var promptToExtendSession = function () {
                $('#sm-countdown-dialog').modal('show');                   
                count = countdownSeconds;
                displayCountdown();
            };

            var refreshSession = function () {
                window.clearInterval(displayCountdownIntervalId);
                var img = new Image(1, 1);
                img.src = extendSessionUrl;
                window.clearTimeout(promptToExtendSessionTimeoutId);
                startSessionManager();
            };

            var startSessionManager = function () {
                promptToExtendSessionTimeoutId =
                    window.setTimeout(promptToExtendSession, secondsBeforePrompt * 1000);
            };

            // Public Functions
            return {
                start: function () {
                    startSessionManager();
                },

                extend: function () {
                    refreshSession();
                }
            };
        }();

        SessionManager.start();

        $('#extendSessionBtn').click(function () {
            SessionManager.extend();
            document.title = originalTitle;
        });

        // Whenever an input changes, extend the session,
        // since we know the user is interacting with the site.
        $(':input').change(function () {
            SessionManager.extend();
        });
    }
    // --------------------------------------------------------------------------------------- //

    $("form button[type=submit]").click(function () {
        isSubmittingProgrammatically = false;
    });

    // When forms are submitted, we want to remove the "disabled" attribute on all form controls so the value is still
    //  submitted in the POST to the controller.  (Excluding the updateOffenderForCCHVal form because we are manually
    //  validating/submitting that form via AJAX request.
    $("form:not(#offenderChangesForm)").submit(function (e) {
        if (isSubmittingProgrammatically) {
            return; // If already submitting programmatically, let it proceed
        }

        let thisForm = $(this);
        if ($(thisForm).valid()) {
            $loading.show();
            $(thisForm).find('input, select, textarea').prop("disabled", false);

            // If reCAPTCHA form, we need to stop submission, and register an event handler to resubmit later
            //  after token is retrieved and stored in the hidden form field.
            if ($(thisForm).hasClass("recaptchaForm")) {
                e.preventDefault();
                let recaptchaAction = $(thisForm).attr('data-recaptcha-action');
                try {
                    // Ensure reCAPTCHA is ready before executing
                    grecaptcha.enterprise.ready(async function () {
                        // Execute reCAPTCHA Enterprise and wait for the token
                        const token = await grecaptcha.enterprise.execute(siteKey, { action: recaptchaAction });
                        $("#RecaptchaToken").val(token);

                        // Since we use the .submit() method to submit the form and it does not trigger submit event handlers,
                        //  we have to manually remove input masks if needed.
                        //removeInputMasksOnSubmit($(thisForm).attr('id'));
                        isSubmittingProgrammatically = true;
                        thisForm.submit();
                    });
                }
                catch (error) {
                    console.error('reCAPTCHA Enterprise execution failed:', error);
                    // Handle errors, such as displaying a message to the user
                    return false;
                }
            }
            return true;
        }
        return false;
    });

    /* Toggle the chevron icons so they point the correct direction depending on if section is collapsed or expanded */
    $('.collapsingSection').on('show.bs.collapse hide.bs.collapse', function () {
        $('a[href="#' + $(this).attr('id') + '"]').children('h2').children('.fa').toggleClass("fa-chevron-down").toggleClass("fa-chevron-right");
    });

    $('.collapsingSection').on('show.bs.collapse', function () {
        $('a[href="#' + $(this).attr('id') + '"]').closest('.panel-heading').children('span').hide();
    });
    $('.collapsingSection').on('hide.bs.collapse', function () {
        $('a[href="#' + $(this).attr('id') + '"]').closest('.panel-heading').children('span').show();
    });

    /****************************************************** Date Pickers ********************************************************/
    $('.dateInput').datepicker({
        showOn: "button",
        minDate: new Date(1900, 1 - 1, 2),
        onClose: function () {
            $(this).trigger('blur');
        }
    });
    $('.dateInput-nonFuture').datepicker({
        showOn: "button",
        minDate: new Date(1900, 1 - 1, 2),
        maxDate: new Date(),
        onClose: function () {
            $(this).trigger('blur');
        }
    });

    $(".dateInputBtn").on('click', function () {
        // When a calendar button is clicked, find the closest preceeding element with the .dateInput or .dateInput-nonFuture class
        //  and show the calendar popup for that datepicker control.
        $(this).prevAll('.dateInput,.dateInput-nonFuture').datepicker("show");
    });

    $(".ui-datepicker-trigger").hide();
    /*****************************************************************************************************************************/

    /************************************************** Input Masks **************************************************************/
    $(".inputMask-phoneNum").inputmask("999-999-9999", { placeholder: " ", removeMaskOnSubmit: false });
    $(".inputMask-zipCode").inputmask("99999-9999", { placeholder: " ", removeMaskOnSubmit: true });
    $(".inputMask-SID").inputmask("999-99-99-9", { placeholder: " ", removeMaskOnSubmit: false });
    $(".dateInput").inputmask("99/99/9999", { placeholder: " ", removeMaskOnSubmit: false });
    $(".dateInput-nonFuture").inputmask("99/99/9999", { placeholder: " ", removeMaskOnSubmit: false });
    $(".dateInput-time").inputmask("99:99", { placeholder: " ", removeMaskOnSubmit: false });
    $(".inputMask-int1").inputmask("9", { placeholder: " ", removeMasKOnSubmit: false });
    $(".inputMask-int2").inputmask("99", { placeholder: " ", removeMasKOnSubmit: false });
    $(".inputMask-int3").inputmask("999", { placeholder: " ", removeMasKOnSubmit: false });
    $(".inputMask-int4").inputmask("9999", { placeholder: " ", removeMasKOnSubmit: false });
    /*****************************************************************************************************************************/

    $('.must-accept-terms').on('click', function (e1) {
        if ($("#termsAcceptedHidden").val() != 'true') {
            e1.preventDefault();
            var tAndCAcceptBtn = document.getElementById('termsAndConditionsAcceptBtn');
            tAndCAcceptBtn.href = this.href;
            if (this.target == '_blank') {
                tAndCAcceptBtn.target = '_blank';
            }
            $('#termsAndConditionsModal').modal('show');
        }
    });

    $('#termsAndConditionsAcceptBtn').on('click', function (e2) {

        // In case of AJAX delay, disable buttons to prevent additional clicks...
        //$('#termsAndConditionsAcceptBtn').attr('disabled', true);
        //$('#termsAndConditionsDeclineBtn').attr('disabled', true);
        $('#termsAndConditionsModal').modal('hide');

        // Send AJAX post to accept Terms and Conditions... then allow link to proceed...
        var url = $("#AcceptTermsAjaxURL").attr("href");
        var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
        var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

        $.ajax({
            url: url,
            data: {
                __RequestVerificationToken: token,
                termsAccepted: true
            },
            cache: false,
            type: "POST",
            success: function (data) {
                if (data.success !== true) {
                    e2.preventDefault();
                }
            },
            error: function (jqXHR, textStatus, errorThrown) {
                $('html').html(jqXHR.responseText);
            }
        });
    });

    // This code is so that a Google map displays properly inside a bootstrap modal dialog...
    $("#mapModal").on("shown.bs.modal", function () {
        var currCenter = map.getCenter();
        google.maps.event.trigger(map, "resize");
        map.setCenter(currCenter);
    });


    //change social media button icon from plus to minus sign when section expanded
    $('#socialMediaBarContent').on('shown.bs.collapse', function () {
        $(this).parent().find(".fa-plus").removeClass("fa-plus").addClass("fa-minus");
    }).on('hidden.bs.collapse', function () {
        $(this).parent().find(".fa-minus").removeClass("fa-minus").addClass("fa-plus");
    });

    var setupSocialMediaBar = function () {
        var ww = document.body.clientWidth;
        if (ww >= 977) {
            $('#socialMediaBarContent').removeClass('collapse');
        } else if (ww < 977) {
            $('#socialMediaBarContent').addClass('collapse');
        };
    };

    //show collapsed social media links on smaller screens
    $(window).resize(function () {
        setupSocialMediaBar();
    });

    setupSocialMediaBar();


    $(".pageLink").click(function (e) {
        e.preventDefault();
    });

    $("#returnToSearch").click(function (e) {
        e.preventDefault();
    });

    $("#mileRadiusMapToggle").click(function (e) {
        e.preventDefault();
    });
});

let isSubmittingProgrammatically = false;

function getGrecaptchaTokenNoSubmit(link) {
    grecaptcha.enterprise.ready(function () {
        grecaptcha.enterprise.execute(siteKey, { action: 'search' }).then(function (token) {
            $("#RecaptchaToken").val(token);
            var href = link.href;
            location.href = href + "&RecaptchaToken=" + token;
        });
    });
}

function removeInputMasksOnSubmit(formId) {
    // Here we want to find all inputs with a mask that have "removeMaskOnSubmit" set to "true"...
    //   because firing the .submit() event will not trigger removal of those automatically as designed by the plugin.k
    $('#' + formId + ' .inputMask-zipCode').each(function () {
        //// Get the unmasked value
        //var unmaskedValue = $(this).inputmask('unmaskedvalue');
        //$(this).val(unmaskedValue);

        // Remove the mask from the original input so the masked value isn't sent
        $(this).inputmask('remove');



        //// Create a hidden field to hold the unmasked value
        //$('<input>')
        //    .attr({
        //        type: 'hidden',
        //        name: 'my-input-unmasked', // Give it a different name if needed
        //        value: unmaskedValue
        //    })
        //    .appendTo($form);
    });    
}

// This can be used with any function to delay execution of that function until the specified time elapses.
//  If a second event fires using this delay method before the time elapses, the time is just reset, rather than running the function twice.
//  Multiple delay references on the same page (for 2 different functions) should be avoided so that wires are not crossed... 
function delay(callback, ms) {
    var timer = 0;
    return function () {
        var context = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function () {
            callback.apply(context, args);
        }, ms || 0);
    };
}

/************************************************** Addresses *********************************************************/
function CityChange(newCity, formControlState, formControlZip, formControlCounty, formControlMunicipality, formControlCountry, formControlRA, oosCityDiv, unknownStateDiv, _setStateCallback, _setCountyCallback, _setMuniCallback, _setAgencyCallback) {
    var oldCounty = formControlCounty.val();
    var oldState = formControlState.val();
    var oldAgency = formControlRA ? formControlRA.val() : null;

    StateSetup(newCity, oldState, formControlState, oosCityDiv, unknownStateDiv, function () {
        if (_setStateCallback != null) { _setStateCallback(); }
        CountiesSetup(newCity, oldCounty, formControlCounty, function () {
            if (_setCountyCallback != null) { _setCountyCallback(); }
            if (formControlMunicipality)
                MunicipalitiesSetup(newCity, oldCounty, formControlCounty.val(), formControlMunicipality, _setMuniCallback);
        });
        CountrySetup(formControlState, formControlCountry, formControlZip);
        if (formControlRA)
            ResponsibleAgenciesSetup(oldState, formControlState.val(), oldAgency, formControlRA, _setAgencyCallback);
    });
}

function StateChange(state, formControlZip, formControlCountry, formControlRA) {
    CountrySetup(state, formControlCountry, formControlZip);
    if (formControlRA)
        ResponsibleAgenciesSetup("", state, formControlRA.val(), formControlRA);
}

function CountyChange(county, city, formControlMunicipality) {
    MunicipalitiesSetup(city, null, county, formControlMunicipality);
}

function StateSetup(city, oldState, formControlState, oosCityDiv, unknownStateDiv, _callback) {
    if (city == "OUT OF STATE") {
        oosCityDiv.show();
        unknownStateDiv.show();

        GetAllStatesExceptPA(formControlState).done(function () {
            formControlState.val("");
            if (_callback != null) { _callback(); }
        });
    }
    else {
        // Don't reload the State and Agency list if it was already set to PA data
        if (oldState != "PA" && oldState != 39) {
            oosCityDiv.hide();
            unknownStateDiv.hide();

            // Get only the "PA" state record and auto-select in on the dropdown.
            GetPAState(formControlState).done(function () {
                formControlState.val("PA");
                // The SVP Victims tab uses the State_LKP_ID as the value instead of the state abbreviation,
                //  so we need to try the value "39" if "PA" isn't on the list...
                if (formControlState.val() != "PA")
                    formControlState.val(39);
                if (_callback != null) { _callback(); }
            });
        }
        else if (_callback != null) {
            _callback();
        }
    }
}

function ResponsibleAgenciesSetup(oldState, newState, oldAgency, formControlRA, _setAgencyCallback) {
    if (newState == "" || newState == null) {
        // Clear out the Resp Agencies dropdown since a state has not been chosen yet.
        var markup = "<option value=''>-- Select Responsible Agency --</option>";
        formControlRA.html(markup).show();
        formControlRA.val("");
        formControlRA.attr("disabled", true);
    }
    else {
        GetResponsibleAgencyNames(newState, formControlRA).done(function () {
            if (_setAgencyCallback != null) { _setAgencyCallback(); }
            // Try to reselect the same agency if the State hasn't changed.
            else if (oldState == newState) {
                formControlRA.val(oldAgency);
            }
        });
    }
}

function CountiesSetup(city, oldCounty, formControlCounty, _callback) {
    if (city == "OUT OF STATE") {
        // If county is not already set to "OUT OF STATE", get the "OUT OF STATE" county record and select it.
        if (oldCounty != "99") {
            GetOutOfStateCounty(formControlCounty).done(function () {
                formControlCounty.val("99");
                if (_callback != null) { _callback(); }
            });
        }
    }
    else
    {
        // Load PA counties, unless a PA county was already selected (meaning the dropdown was already loaded with PA counties.)
        if (oldCounty == "" || oldCounty == null || oldCounty == 0 || oldCounty == 99) {
            GetCounties(formControlCounty).done(function () {
                if (_callback != null) { _callback(); }
            });
        }
        else {
            if (_callback != null) { _callback(); }
        }
    }
}

function MunicipalitiesSetup(city, oldCounty, newCounty, formControlMunicipality, _setMuniCallback) {
    // Only reload the Municipalities dropdown if the County selection changed.
    if (oldCounty != newCounty) {
        // Get the "OUT OF STATE" municipality option and select it, if it is not already loaded/selected.
        if (city == "OUT OF STATE" || newCounty == "99") {
                if (formControlMunicipality.val() != "99") {
                GetMunicipalities("99", formControlMunicipality).done(function () {
                    formControlMunicipality.val("2647");
                });
            }
        }
        // No county is selected, so empty and disable the Municipality dropdown
        else if (newCounty == "" || newCounty == null || newCounty == 0) {
            var markup = "<option value=''>-- Select Municipality --</option>";
            formControlMunicipality.html(markup).show();
            formControlMunicipality.val("");
            formControlMunicipality.attr("disabled", true);
        }
        else {
            GetMunicipalities(newCounty, formControlMunicipality).done(function () {
                if (_setMuniCallback != null) { _setMuniCallback(); }
            });
        }
    }
}

function CountrySetup(newState, formControlCountry, formControlZip) {
    // Reload only US as the country if they changed the State from Unknown to something else.
    // Also reload the US value only if it's not already there (going from US state to another US state.)
    if (newState != "XX" && newState != 97 && formControlCountry.val() != "312") {
        GetUSCountry(formControlCountry);
        formControlZip.inputmask("99999-9999", { placeholder: " ", removeMaskOnSubmit: true });
    }
    else if (newState == "XX" || newState == 97) {  // State changed from a US State to "Unknown"
        GetAllCountries(formControlCountry);
        formControlZip.inputmask("**********", { placeholder: "", removeMaskOnSubmit: true });
    }
}

/******************************************************** AJAX Requests *****************************************************/
function GetCountries(_StateId, formControlCountry) {
    $(formControlCountry).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetCountriesURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token,
            stateid: _StateId
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlCountry).html('');
            $(formControlCountry).append($('<option>', {
                'value': '',
                'text': '-- Select Country --'
            }));

            for (var x = 0; x < data.length; x++) {
                $(formControlCountry).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }
            formControlCountry.show();

            //After the dropdown list is refreshed, check to see if "UNKNOWN" was selected...
            //  If it was not (a U.S. state, or nothing was selected), disable the country dropdown.
            if (_StateId != "97") {
                formControlCountry.prop("disabled", true);
                // Only show the single country "U.S." and select it.
                if (_StateId != "") {
                    formControlCountry.val("312"); // Set to U.S.
                }
            }
            else formControlCountry.prop("disabled", false);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetOutOfStateCounty(formControlCounty) {
    $(formControlCounty).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetoutOfStateCountyURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlCounty).html('');
            if (data.length > 1) {
                $(formControlCounty).append($('<option>', {
                    'value': '',
                    'text': '-- Select County --'
                }));
            }
            for (var x = 0; x < data.length; x++) {
                $(formControlCounty).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }

            formControlCounty.show();
            formControlCounty.attr("disabled", true);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetCounties(formControlCounty) {
    $(formControlCounty).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetCountiesURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlCounty).html('');
            if (data.length > 1) {
                $(formControlCounty).append($('<option>', {
                    'value': '',
                    'text': '-- Select County --'
                }));
            }
            for (var x = 0; x < data.length; x++) {
                $(formControlCounty).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }

            formControlCounty.show();
            formControlCounty.attr("disabled", false);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetAllStates(formControlState) {
    $(formControlState).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetAllStatesURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlState).html('');
            if (data.length > 1) {
                $(formControlState).append($('<option>', {
                    'value': '',
                    'text': '-- Select State --'
                }));
                //markup += "<option value=''>-- Select State --</option>";
            }

            for (var x = 0; x < data.length; x++) {
                $(formControlState).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
                //markup += "<option value=" + data[x].Value + ">" + data[x].Text + "</option>";
            }
            //formControlState.html(markup).show();
            formControlState.show();
            formControlState.attr("disabled", false);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetAllStatesExceptPA(formControlState) {
    //var procemessage = "<option value='0'> Please wait...</option>";
    //formControlState.html(procemessage).show();
    $(formControlState).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $('#GetAllStatesExceptPAURL').attr('href');//"/GlobalLookups/GetAllStatesExceptPA";
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token,
        },
        cache: false,
        type: "POST",
        dataType: "json",
        success: function (data) {
            $(formControlState).html('');
            //var markup = "";
            if (data.length > 1) {
                //markup += "<option value=''>-- Select State --</option>";
                $(formControlState).append($('<option>', {
                    'value': '',
                    'text': '-- Select State --'
                }));
            }

            for (var x = 0; x < data.length; x++) {
                $(formControlState).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
                //markup += "<option value=" + data[x].Value + ">" + data[x].Text + "</option>";
            }
            formControlState.show();
            formControlState.attr("disabled", false);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetPAState(formControlState) {
    //var procemessage = "<option value='0'> Please wait...</option>";
    //formControlState.html(procemessage).show();
    $(formControlState).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetPAStateURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlState).html('');
            if (data.length > 1) {
                //markup += "<option value=''>-- Select State --</option>";
                $(formControlState).append($('<option>', {
                    'value': '',
                    'text': '-- Select State --'
                }));
            }

            for (var x = 0; x < data.length; x++) {
                //markup += "<option value=" + data[x].Value + ">" + data[x].Text + "</option>";
                $(formControlState).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }
            formControlState.show();
            formControlState.attr("disabled", true);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetAllCountries(formControlCountry) {
    $(formControlCountry).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetAllCountriesURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlCountry).html('');
            if (data.length > 1) {
                $(formControlCountry).append($('<option>', {
                    'value': '',
                    'text': '-- Select Country --'
                }));
            }

            for (var x = 0; x < data.length; x++) {
                $(formControlCountry).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }
            formControlCountry.show();
            formControlCountry.attr("disabled", false);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetUSCountry(formControlCountry) {
    $(formControlCountry).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetUSCountryURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlCountry).html('');
            if (data.length > 1) {
                $(formControlCountry).append($('<option>', {
                    'value': '',
                    'text': '-- Select Country --'
                }));
            }

            for (var x = 0; x < data.length; x++) {
                $(formControlCountry).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }
            formControlCountry.show();
            formControlCountry.attr("disabled", true);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetMunicipalities(_CountyCode, formControlMunicipality) {
    $(formControlMunicipality).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $("#GetMunicipalitiesURL").attr("href");
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token,
            countycode: _CountyCode
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlMunicipality).html('');
            if (data.length > 1) {
                $(formControlMunicipality).append($('<option>', {
                    'value': '',
                    'text': '-- Select Municipality --'
                }));
            }

            for (var x = 0; x < data.length; x++) {
                $(formControlMunicipality).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }

            formControlMunicipality.show();
            formControlMunicipality.attr("disabled", false);
            // If there is only one option and it is "OUT OF STATE", disable the dropdown.
            if (data.length == 1) {
                if (data[0].Value == 2647) {
                    formControlMunicipality.attr("disabled", true);
                }
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}

function GetResponsibleAgencyNames(state, formControlRA) {
    $(formControlRA).html($('<option>', {
        'value': '0',
        'text': 'Please wait...'
    })).show();

    var url = $('#GetResponsibleAgenciesURL').attr('href');
    var ajaxAntiForgeryForm = $('#__AjaxAntiForgeryForm');
    var token = $('input[name="__RequestVerificationToken"]', ajaxAntiForgeryForm).val();

    return $.ajax({
        url: url,
        data: {
            __RequestVerificationToken: token,
            state: state
        },
        cache: false,
        type: "POST",
        success: function (data) {
            $(formControlRA).html('');
            if (data.length > 1) {
                $(formControlRA).append($('<option>', {
                    'value': '',
                    'text': '-- Select Responsible Agency --'
                }));
            }

            for (var x = 0; x < data.length; x++) {
                $(formControlRA).append($('<option>', {
                    'value': data[x].Value,
                    'text': data[x].Text
                }));
            }
            formControlRA.show();
            formControlRA.attr("disabled", false);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            $('html').html(jqXHR.responseText);
        }
    });
}
function PageSetup() {
    var amountScrolled = 300;
    $(window).scroll(function () {
        if ($(window).scrollTop() > amountScrolled) {
            $('a.back-to-top').fadeIn('slow');
        } else {
            $('a.back-to-top').fadeOut('slow');
        }
    });

    $('a.back-to-top').click(function () {
        $('html, body').animate({
            scrollTop: 0
        }, 700);
        return false;
    });
};
myValidationNamespace = {
    getDependentProperyID: function (validationElement, dependentProperty) {
        if (document.getElementById(dependentProperty)) {
            return dependentProperty;
        }
        var name = validationElement.name;
        var index = name.lastIndexOf(".") + 1;
        dependentProperty = (name.substr(0, index) + dependentProperty).replace(/[\.\[\]]/g, "_");
        if (document.getElementById(dependentProperty)) {
            return dependentProperty;
        }
        return null;
    }
}



// Extend range validator method to treat checkboxes differently
// This allows us to require a checkbox be checked (true) by using the following
// model validation attribute:  [Range(typeof(bool), "true", "true", ErrorMessage = "Checkbox must be checked!")]
var defaultRangeValidator = $.validator.methods.range;
$.validator.methods.range = function (value, element, param) {
    if (element.type === 'checkbox') {
        // if it's a checkbox return true if it is checked
        return element.checked;
    } else {
        // otherwise run the default validation function
        return defaultRangeValidator.call(this, value, element, param);
    }
}

/************************************************************************************************************
    Make sure the entered date (DOB) is after the date passed as a parameter ("01/01/1900")
************************************************************************************************************/
$.validator.unobtrusive.adapters.add(
    'dateafter',
    ['comparedate'],
    function (options) {
        options.rules['dateafter'] = options.params;
        if (options.message) {
            options.messages['dateafter'] = options.message;
        }
    }
);

$.validator.addMethod(
    "dateafter",
    function (value, element, params) {
        // If this is a valid date... 
        if (!/Invalid|NaN/.test(new Date(value))) {

            var valDateArray = value.split("/");
            var paramDateArray = ["01", "01", "1800"];

            if (params.comparedate != null)
                paramDateArray = params.comparedate.split("/");
            else if (params != null)
                paramDateArray = params.split("/");

            var valYear = parseInt(valDateArray[2]);
            var paramYear = parseInt(paramDateArray[2]);

            var valMonth = parseInt(valDateArray[0]);
            var paramMonth = parseInt(paramDateArray[0]);

            var valDay = parseInt(valDateArray[1]);
            var paramDay = parseInt(paramDateArray[1]);

            // ...if the year entered is >= the year of the parameter date
            if (valYear >= paramYear) {
                // if the year entered is greater, we know the date passes validation -- no need to check month/day
                if (valYear > paramYear) {
                    return true;
                }
                    // Year entered matches the year of the date parameter
                else {
                    // If the month entered is >= the month of the parameter date
                    if (valMonth >= paramMonth) {
                        // if the month entered is greater, we know the date passes validation -- no need to check day
                        if (valMonth > paramMonth) {
                            return true;
                        }
                            // Month & Year entered matches the month/year of the date parameter
                        else {
                            if (valDay >= paramDay) {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }
        return true;
    },
    $.validator.format("Date must be after {0}.")
);

/************************************************************************************************************
    Check to make sure that the date entered is after the date of the specified property
************************************************************************************************************/

$.validator.unobtrusive.adapters.add('dateaftercompare', ['comparedatefield', 'equalto'], function (options) {
    options.rules['dateaftercompare'] = options.params;
    if (options.message) {
        options.messages['dateaftercompare'] = options.message;
    }

    var element = options.element;
    var comparedatefield = options.params.comparedatefield;
    comparedatefield = myValidationNamespace.getDependentProperyID(element, comparedatefield);
    options.rules['dateaftercompare'].comparedatefield = comparedatefield;
});

$.validator.addMethod(
    "dateaftercompare",
    function (value, element, params) {
        if ($('#' + params.comparedatefield).val() == null || $('#' + params.comparedatefield).val() == "") {
            return true;
        }

        // If this is a valid date... 
        if (!/Invalid|NaN/.test(new Date(value))) {
            var valDateArray = value.split("/");
            var paramDateArray = ["01", "01", "1800"];

            if (params.comparedatefield != null)
                paramDateArray = $('#' + params.comparedatefield).val().split("/");
            else if (params != null)
                paramDateArray = $('#' + params).val().split("/");

            var valYear = parseInt(valDateArray[2]);
            var paramYear = parseInt(paramDateArray[2]);

            var valMonth = parseInt(valDateArray[0]);
            var paramMonth = parseInt(paramDateArray[0]);

            var valDay = parseInt(valDateArray[1]);
            var paramDay = parseInt(paramDateArray[1]);

            // If option equalTo parameter is false, return true if dates match
            var equalTo = params.equalto;
            if (equalTo == "False" && valYear == paramYear && valMonth == paramMonth && valDay == paramDay) {
                return false;
            }

            // ...if the year entered is >= the year of the parameter date
            if (valYear >= paramYear) {
                // if the year entered is greater, we know the date passes validation -- no need to check month/day
                if (valYear > paramYear) {
                    return true;
                }
                    // Year entered matches the year of the date parameter
                else {
                    // If the month entered is >= the month of the parameter date
                    if (valMonth >= paramMonth) {
                        // if the month entered is greater, we know the date passes validation -- no need to check day
                        if (valMonth > paramMonth) {
                            return true;
                        }
                            // Month & Year entered matches the month/year of the date parameter
                        else {
                            if (valDay >= paramDay) {
                                return true;
                            }
                        }
                    }
                }
            }


            return false;
        }
        return true;
    },
    $.validator.format("Date must be after {0}.")
);

/************************************************************************************************************
    Check if this is actually a valid calendar date. (The default jQuery Validation's "date" rule only checks if the string entered CAN be converted to a valid date --
    the JavaScript will transform the value just to make it work...  For example, 0/42/2011 becomes the valid date "2/11/2011".
************************************************************************************************************/
$.validator.unobtrusive.adapters.add(
    'realdate',
    function (options) {
        options.rules['realdate'] = options.params;
        if (options.message) {
            options.messages['realdate'] = options.message;
        }
    }
);

$.validator.addMethod(
    "realdate",
    function (value, element, options) {
        if (value != null && value != "") {
            // If this is a valid date format... 
            if (!/Invalid|NaN/.test(new Date(value))) {
                var dateArray = value.split('/');
                var m = parseInt(dateArray[0], 10);
                var d = parseInt(dateArray[1], 10);
                var y = parseInt(dateArray[2], 10);
                var date = new Date(y, m - 1, d);
                if (date.getFullYear() == y && date.getMonth() + 1 == m && date.getDate() == d && y >= 1753) {
                    return true
                } else {
                    return false;
                }
            }
            return false;
        }
        return true;
    },
    $.validator.format("Please enter a valid date.")
);

/************************************************************************************************************
    Check if this is a future date.
************************************************************************************************************/
$.validator.unobtrusive.adapters.add(
    'nonfuturedate',
    function (options) {
        options.rules['nonfuturedate'] = options.params;
        if (options.message) {
            options.messages['nonfuturedate'] = options.message;
        }
    }
);

$.validator.addMethod(
    "nonfuturedate",
    function (value, element, options) {
        // If this is a valid date format... 
        if (!/Invalid|NaN/.test(new Date(value))) {
            if (new Date(value) > new Date()) {
                return false;
            }
        }
        return true;
    },
    $.validator.format("You may not enter a date in the future.")
);

/************************************************************************************************************
    Verify EndDate is in the past if the IsCurrent flag is set.
************************************************************************************************************/
$.validator.unobtrusive.adapters.add(
    'enddatecurrent',
    function (options) {
        options.rules['enddatecurrent'] = options.params;
        if (options.message) {
            options.messages['enddatecurrent'] = options.message;
        }
    }
);

$.validator.addMethod(
    "enddatecurrent",
    function (value, element, options) {
        var endDate = new Date(value);
        // If this is a valid date format... 
        if (!/Invalid|NaN/.test(endDate)) {
            var todaysDate = new Date();
            var isCurrentCtrl = $("input[id$='chkIsCurrent']:checked");
            if (isCurrentCtrl.length) {
                if (isCurrentCtrl.val().toLowerCase() === "true" && endDate < todaysDate) {
                    return false;
                }
            }
        }
        return true;
    }
);

/************************************************************************************************************
    For Temporary addresses, verify date range is at least 7 days.
************************************************************************************************************/
$.validator.unobtrusive.adapters.add('tempaddressminlength', ['startdatefield', 'addresstypefield'], function (options) {
    options.rules['tempaddressminlength'] = options.params;
    if (options.message) {
        options.messages['tempaddressminlength'] = options.message;
    }
    var element = options.element;

    var startdatefield = options.params.startdatefield;
    startdatefield = myValidationNamespace.getDependentProperyID(element, startdatefield);
    options.rules['tempaddressminlength'].startdatefield = startdatefield;

    var addresstypefield = options.params.addresstypefield;
    addresstypefield = myValidationNamespace.getDependentProperyID(element, addresstypefield);
    options.rules['tempaddressminlength'].addresstypefield = addresstypefield;
});

$.validator.addMethod(
    "tempaddressminlength",
    function (value, element, params) {
        var endDate = new Date(value);
        // If this is a valid date format... 
        if (!/Invalid|NaN/.test(endDate)) {
            var startDate = new Date($('#' + params.startdatefield).val());
            var oneDay = 24 * 60 * 60 * 1000; // hours*minutes*seconds*milliseconds
            var diffDays = Math.round(Math.abs((startDate.getTime() - endDate.getTime()) / (oneDay)));
            if ($('#' + params.addresstypefield).val() === "Temporary" && diffDays < 6) {
                return false;
            }
        }
        return true;
    }
);


/************************************************************************************************************
    Only require input for an element if another property's value matches the desired value
************************************************************************************************************/
$.validator.unobtrusive.adapters.add('requiredif', ['dependentproperty', 'desiredvalue', 'multiplevalues'], function (options) {
    options.rules['requiredif'] = options.params;
    options.messages['requiredif'] = options.message;

    var element = options.element;
    var dependentproperty = options.params.dependentproperty;
    dependentproperty = myValidationNamespace.getDependentProperyID(element, dependentproperty);
    options.rules['requiredif'].dependentproperty = dependentproperty;
});

$.validator.addMethod('requiredif', function (value, element, parameters) {

    // If there are multiple possible values that should trigger "required" validation, assume they are a JSON string array
    //   and loop through them.  If ANY are found to match the current value, perform validation.
    if (parameters.multiplevalues == "True")
    {
        var desiredValues = JSON.parse(parameters.desiredvalue);
        for (var i = 0; i < desiredValues.length; i++) {
            var desiredvalue = desiredValues[i];
            desiredvalue = (desiredvalue == null ? '' : desiredvalue).toString();
            var actualvalue = {};

            //var controlType = $("input[name='" + parameters.dependentproperty + "']").attr("type");
            var controlType = $("#" + parameters.dependentproperty).attr("type");
            if (controlType == "checkbox" || controlType == "radio") {
                //var controlId = $("input[name='" + parameters.dependentproperty + "']:checked").attr("id");
                actualvalue = $("#" + parameters.dependentproperty).is(":checked");
            }
            else //if (controlType == 'text' || controlType == 'hidden') {
                //actualvalue = $("input[name='" + parameters.dependentproperty + "'").val();
            //} else {
            //    actualvalue = $("select[name='" + parameters.dependentproperty + "'] option:selected").val();
            //    if (actualvalue == null)
            //    {
                    actualvalue = $("#" + parameters.dependentproperty).val();
            //    }
            //}

            if ($.trim(desiredvalue).toLowerCase() === $.trim(actualvalue).toLocaleLowerCase()) {
                var isValid = $.validator.methods.required.call(this, $.trim(value), element, parameters);
                return isValid;
            }
        }
    }
    //  If there is only one possible value that will trigger "required" validation, then evaluate it normally.
    else {
        var desiredvalue = parameters.desiredvalue;
        desiredvalue = (desiredvalue == null ? '' : desiredvalue).toString();
        var actualvalue = {}

        var controlType = $("#" + parameters.dependentproperty).attr("type");
        if (controlType == "checkbox" || controlType == "radio") {
            actualvalue = $("#" + parameters.dependentproperty).is(":checked");
        }
        else {
            actualvalue = $("#" + parameters.dependentproperty).val();
        }

        if ($.trim(desiredvalue).toLowerCase() === $.trim(actualvalue).toLocaleLowerCase()) {
            var isValid = $.validator.methods.required.call(this, $.trim(value), element, parameters);
            return isValid;
        }
    }

    return true;
});

/************************************************************************************************************
    Only require input for an element if another property's value matches the desired value
************************************************************************************************************/
$.validator.unobtrusive.adapters.add('requiredifmultiple', ['rules'], function (options) {
    //options.rules['requiredifmultiple'] = options.params;
    options.messages['requiredifmultiple'] = options.message;

    var element = options.element;
    var rulesArray = JSON.parse(options.params.rules);
    for (var j = 0; j < rulesArray.length; j++) {
        var fullPropertyName = rulesArray[j].PropertyName;
        fullPropertyName = myValidationNamespace.getDependentProperyID(element, fullPropertyName);
        rulesArray[j].PropertyName = fullPropertyName;
    }
    options.params.rules = JSON.stringify(rulesArray);
    options.rules['requiredifmultiple'] = options.params;

});

$.validator.addMethod('requiredifmultiple', function (value, element, parameters) {

    // If there are multiple possible values that should trigger "required" validation, assume they are a JSON string array
    //   and loop through them.  If ANY are found to match the current value, perform validation.
    
    var rulesArray = JSON.parse(parameters.rules);
    var ruleResultArray = [];

    for (var j = 0; j < rulesArray.length; j++) {

        var ruleResult = true;
        var desiredValues = rulesArray[j].DesiredValue;

        for (var i = 0; i < desiredValues.length; i++) {
            
            var desiredvalue = desiredValues[i];
            desiredvalue = (desiredvalue == null ? '' : desiredvalue).toString();
            var actualvalue = {};
            var controlType = $("#" + rulesArray[j].PropertyName).attr("type");
            if (controlType == "checkbox" || controlType == "radio") {
                actualvalue = $("#" + rulesArray[j].PropertyName).is(":checked");
            }
            else {
                actualvalue = $("#" + rulesArray[j].PropertyName).val();
            }

            if ($.trim(desiredvalue).toLowerCase() === $.trim(actualvalue).toLocaleLowerCase()) {
                var isValid = $.validator.methods.required.call(this, $.trim(value), element, parameters);
                if (!isValid) {
                    ruleResult = false;
                }
            }
        }

        ruleResultArray.push(ruleResult);
    }

    for (var k = 0; k < ruleResultArray.length; k++) {
        if (ruleResultArray[k] === true) {
            return true;
        }
    }

    return false;

});

/************************************************************************************************************
    Add regular expression validation to an element if a given condition exists
************************************************************************************************************/
$.validator.unobtrusive.adapters.add('regularexpressionif', ['dependentproperty', 'desiredvalue', 'pattern', 'multiplevalues'], function (options) {
    options.rules['regularexpressionif'] = options.params;
    options.messages['regularexpressionif'] = options.message;

    var element = options.element;
    var dependentproperty = options.params.dependentproperty;
    dependentproperty = myValidationNamespace.getDependentProperyID(element, dependentproperty);
    options.rules['regularexpressionif'].dependentproperty = dependentproperty;
});

$.validator.addMethod('regularexpressionif', function (value, element, parameters) {
    //var dependentproperty = parameters.dependentproperty;
    //if (!$("#" + dependentproperty).length)
    //    dependentproperty = "ddl" + dependentproperty;

    // If there are multiple possible values that should trigger the validation, assume they are a JSON string array
    //   and loop through them.  If ANY are found to match the current value, perform validation.
    if (parameters.multiplevalues == "True")
    {
        var desiredValues = JSON.parse(parameters.desiredvalue);
        for (var i = 0; i < desiredValues.length; i++) {
            var desiredvalue = desiredValues[i];
            desiredvalue = (desiredvalue == null ? '' : desiredvalue).toString();

            var dependentControlType = $("#" + parameters.dependentproperty).attr("type");
            var comparisonValue = {}
            if (dependentControlType == "checkbox" || dependentControlType == "radio")
                comparisonValue = $("#" + parameters.dependentproperty).is(":checked");
            else
                comparisonValue = $("#" + parameters.dependentproperty).val();

            if ($.trim(desiredvalue).toLowerCase() === $.trim(comparisonValue).toLocaleLowerCase()) {
                var patt = new RegExp(parameters.pattern);
                return patt.test(value);
            }
        }
    }
    //  If there is only one possible value that will trigger then validation, then evaluate it normally.
    else {
        var desiredvalue = parameters.desiredvalue;
        desiredvalue = (desiredvalue == null ? '' : desiredvalue).toString();
        //var dependentControlType = $("input[id$='" + dependentproperty + "']").attr("type");
        var dependentControlType = $("#" + parameters.dependentproperty).attr("type");
        var comparisonValue = {}
        if (dependentControlType == "checkbox" || dependentControlType == "radio") {
            //var dependentControl = $("input[id$='" + dependentproperty + "']").attr("name");
            //comparisonValue = $("input[name$='" + dependentControl + "']:checked").length !== 0;
            comparisonValue = $("#" + parameters.dependentproperty).is(":checked");
        }
        else {
            comparisonValue = $("#" + parameters.dependentproperty).val();
        }

        if ($.trim(desiredvalue).toLowerCase() === $.trim(comparisonValue).toLocaleLowerCase()) {
            var patt = new RegExp(parameters.pattern);
            return patt.test(value);
        }
    }

    return true;
});

/************************************************************************************************************
    Add regular expression validation to an element if multiple conditions exists
************************************************************************************************************/
$.validator.unobtrusive.adapters.add('regularexpressionifmultiple', ['rules', 'pattern'], function (options) {
    //options.rules['regularexpressionifmultiple'] = options.params;
    options.messages['regularexpressionifmultiple'] = options.message;

    var element = options.element;
    var rulesArray = JSON.parse(options.params.rules);
    for (var j = 0; j < rulesArray.length; j++) {
        var fullPropertyName = rulesArray[j].PropertyName;
        fullPropertyName = myValidationNamespace.getDependentProperyID(element, fullPropertyName);
        rulesArray[j].PropertyName = fullPropertyName;
    }
    options.params.rules = JSON.stringify(rulesArray);
    options.rules['regularexpressionifmultiple'] = options.params;

});

$.validator.addMethod('regularexpressionifmultiple', function (value, element, parameters) {

    // If there are multiple possible values that should trigger "required" validation, assume they are a JSON string array
    //   and loop through them.  If ANY are found to match the current value, perform validation.
    var rulesArray = JSON.parse(parameters.rules);
    var ruleResultArray = [];

    for (var j = 0; j < rulesArray.length; j++) {

        var ruleResult = true;
        var desiredValues = rulesArray[j].DesiredValue;

        for (var i = 0; i < desiredValues.length; i++) {

            var desiredvalue = desiredValues[i];
            desiredvalue = (desiredvalue == null ? '' : desiredvalue.toString());

            var actualvalue = {};
            var controlType = $("#" + rulesArray[j].PropertyName).attr("type");
            if (controlType == "checkbox" || controlType == "radio") {
                actualvalue = $("#" + rulesArray[j].PropertyName).is(":checked");
            }
            else {
                actualvalue = $("#" + rulesArray[j].PropertyName).val();
            }

            if ($.trim(desiredvalue).toLowerCase() === $.trim(actualvalue).toLocaleLowerCase()) {
                var patt = new RegExp(parameters.pattern);
                if (!patt.test(value)) {
                    ruleResult = false;
                }
            }
        }

        ruleResultArray.push(ruleResult);
    }

    for (var k = 0; k < ruleResultArray.length; k++) {
        if (ruleResultArray[k] === true) {
            return true;
        }
    }

    return false;
});

/************************************************************************************************************
    Customize the "require_from_group" rule originally included with jQuery Validate additional-methods.js file.
    The problem with the original rule was that it doesn't work for multiple select lists -- If a multi-select list
    is included in a require group, that group always passes validation even if nothing is selected.

    This counts [], [""], and [0] as empty.
    This counts 0 as empty as well, matching original function. You could remove that by dropping the && valStr != '0'
************************************************************************************************************/
$.validator.addMethod("require_from_group", function (value, element, options) {
    var $fields = $(options[1], element.form),
		$fieldsFirst = $fields.eq(0),
		validator = $fieldsFirst.data("valid_req_grp") ? $fieldsFirst.data("valid_req_grp") : $.extend({}, this),
		isValid = $fields.filter(function () {
		    if (validator.elementValue(this) != null) {
		        var valStr = validator.elementValue(this).toString()
		        return valStr && valStr != '0';
		    }
		    else
		        return false;
		}).length >= options[0];

    // Store the cloned validator for future validation
    $fieldsFirst.data("valid_req_grp", validator);

    // If element isn't being validated, run each require_from_group field's validation rules
    if (!$(element).data("being_validated")) {
        $fields.data("being_validated", true);
        $fields.each(function () {
            validator.element(this);
        });
        $fields.data("being_validated", false);
    }
    return isValid;
}, $.validator.format("Please enter at least {0} of these fields."));

$.validator.unobtrusive.adapters.add(
    "requirefromgroup", ["number", "selector"], function (options) {
        options.rules["require_from_group"] = [options.params.number, options.params.selector];
        options.messages["require_from_group"] = options.message;
    }
);;
