(function (window, document, $) {
    'use strict';

    if (!$) {
        return;
    }

    function route(path) {
        var base = (window.NGBVD_BASE_URL || '').replace(/\/$/, '');
        return base + path;
    }

    function getSelectize($select) {
        if ($select && $select.length && $select[0].selectize) {
            return $select[0].selectize;
        }
        return null;
    }

    function clearAndFillSelect($select, items, placeholder, options) {
        options = options || {};
        if (!$select || !$select.length) {
            return;
        }

        var selectize = getSelectize($select);
        var requiredWhenEmpty = options.requiredWhenEmpty !== false;

        if (selectize) {
            selectize.clear(true);
            selectize.clearOptions();
            selectize.addOption({ value: '', text: placeholder || 'Choose One' });
            $.each(items || [], function (_, item) {
                selectize.addOption({ value: String(item.id), text: item.name });
            });
            selectize.refreshOptions(false);
            selectize.setValue('', true);
        } else {
            $select.empty();
            $select.append($('<option>', { value: '', text: placeholder || 'Choose One' }));
            $.each(items || [], function (_, item) {
                $select.append($('<option>', { value: item.id, text: item.name }));
            });
        }

        if ((items || []).length === 0 && !requiredWhenEmpty) {
            $select.prop('required', false);
        } else if (options.forceRequired) {
            $select.prop('required', true);
        }
    }

    function findSelectByNames(names) {
        var selectors = [];
        $.each(names, function (_, name) {
            selectors.push('#' + name);
            selectors.push('select[name="' + name + '"]');
        });
        return $(selectors.join(',')).first();
    }

    function showLoading($select, text) {
        clearAndFillSelect($select, [], text || 'Loading...', { requiredWhenEmpty: false });
    }

    function wireLocationCascade() {
        $(document).off('change.ngbvdLocation', '#district, select[name="districtid"]')
            .on('change.ngbvdLocation', '#district, select[name="districtid"]', function () {
                var districtId = $(this).val();
                var $subcounty = findSelectByNames(['subcountyid', 'subcounty']);
                var $parish = findSelectByNames(['parishid', 'parish']);
                var $village = findSelectByNames(['village', 'villageid']);

                clearAndFillSelect($parish, [], 'Choose Sub-county First', { requiredWhenEmpty: false });
                clearAndFillSelect($village, [], 'Choose Parish First', { requiredWhenEmpty: false });

                if (!districtId || !$subcounty.length) {
                    clearAndFillSelect($subcounty, [], 'Choose District First', { requiredWhenEmpty: false });
                    return;
                }

                showLoading($subcounty, 'Loading sub-counties...');
                $.getJSON(route('/findSubcounty'), { id: districtId })
                    .done(function (data) {
                        clearAndFillSelect($subcounty, data, 'Choose Sub-county', { forceRequired: true });
                    })
                    .fail(function () {
                        clearAndFillSelect($subcounty, [], 'Unable to load sub-counties', { requiredWhenEmpty: false });
                    });
            });

        $(document).off('change.ngbvdLocationSub', '#subcountyid, select[name="subcountyid"]')
            .on('change.ngbvdLocationSub', '#subcountyid, select[name="subcountyid"]', function () {
                var subcountyId = $(this).val();
                var $parish = findSelectByNames(['parishid', 'parish']);
                var $village = findSelectByNames(['village', 'villageid']);

                clearAndFillSelect($village, [], 'Choose Parish First', { requiredWhenEmpty: false });

                if (!subcountyId || !$parish.length) {
                    clearAndFillSelect($parish, [], 'Choose Sub-county First', { requiredWhenEmpty: false });
                    return;
                }

                showLoading($parish, 'Loading parishes...');
                $.getJSON(route('/findParish'), { id: subcountyId })
                    .done(function (data) {
                        clearAndFillSelect($parish, data, 'Choose Parish', { forceRequired: true });
                    })
                    .fail(function () {
                        clearAndFillSelect($parish, [], 'Unable to load parishes', { requiredWhenEmpty: false });
                    });
            });

        $(document).off('change.ngbvdLocationParish', '#parishid, select[name="parishid"]')
            .on('change.ngbvdLocationParish', '#parishid, select[name="parishid"]', function () {
                var parishId = $(this).val();
                var $village = findSelectByNames(['village', 'villageid']);

                if (!$village.length) {
                    return;
                }

                if (!parishId) {
                    clearAndFillSelect($village, [], 'Choose Parish First', { requiredWhenEmpty: false });
                    return;
                }

                showLoading($village, 'Loading villages...');
                $.getJSON(route('/findVillage'), { id: parishId })
                    .done(function (data) {
                        clearAndFillSelect($village, data, 'Choose Village', { requiredWhenEmpty: false });
                    })
                    .fail(function () {
                        clearAndFillSelect($village, [], 'Unable to load villages', { requiredWhenEmpty: false });
                    });
            });
    }

    function wireNationalStatusCascade() {
        $(document).off('change.ngbvdNationalStatus', '#nstatus, #national_status, select[name="national_status"]')
            .on('change.ngbvdNationalStatus', '#nstatus, #national_status, select[name="national_status"]', function () {
                var statusId = $(this).val();
                var $category = findSelectByNames(['ns_categornsy', 'national_status_category', 'national_status_category_id']);

                if (!$category.length && $('#ns_category').length) {
                    $('#ns_category').html('<select class="form-control search-select" name="ns_categornsy" id="ns_categornsy"></select>');
                    $category = $('#ns_categornsy');
                }

                if (!$category.length) {
                    return;
                }

                if (!statusId) {
                    clearAndFillSelect($category, [], 'Choose Nationality Status First', { requiredWhenEmpty: false });
                    return;
                }

                showLoading($category, 'Loading categories...');
                $.getJSON(route('/findNSCategory'), { id: statusId })
                    .done(function (data) {
                        if ((data || []).length === 0) {
                            clearAndFillSelect($category, [], 'No category configured', { requiredWhenEmpty: false });
                            $category.prop('required', false);
                            return;
                        }
                        clearAndFillSelect($category, data, 'Choose Category', { forceRequired: true });
                    })
                    .fail(function () {
                        clearAndFillSelect($category, [], 'Unable to load categories', { requiredWhenEmpty: false });
                    });
            });
    }

    function wireReferenceToSurvivorCode() {
        $(document).off('input.ngbvdReferenceCode change.ngbvdReferenceCode', '#crb_number, input[name="crb_number"]')
            .on('input.ngbvdReferenceCode change.ngbvdReferenceCode', '#crb_number, input[name="crb_number"]', function () {
                var reference = $(this).val();
                $('#survivor_code, input[name="survivor_code"]').val(reference);
            });

        $(document).off('submit.ngbvdReferenceCode', 'form')
            .on('submit.ngbvdReferenceCode', 'form', function () {
                var $reference = $(this).find('#crb_number, input[name="crb_number"]').first();
                var $survivorCode = $(this).find('#survivor_code, input[name="survivor_code"]').first();
                if ($reference.length && $survivorCode.length) {
                    $survivorCode.val($reference.val());
                }
            });
    }

    $(function () {
        wireLocationCascade();
        wireNationalStatusCascade();
        wireReferenceToSurvivorCode();

        var $reference = $('#crb_number, input[name="crb_number"]').first();
        if ($reference.length) {
            $('#survivor_code, input[name="survivor_code"]').val($reference.val());
        }
    });
})(window, document, window.jQuery);
