const getStoredTheme = () => localStorage.getItem("theme");
const setStoredTheme = theme => localStorage.setItem("theme", theme);
const getPreferredTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';

$('input[name="themeToggle"]').on("change", function() {
    const selectedTheme = $(this).val();
    setStoredTheme(selectedTheme);
    setThemeIcon(selectedTheme)
    applyTheme(selectedTheme);
});

// on page load
function initThemeChoice() {
    const theme = getStoredTheme() || "auto";  // If the user is new, they won't have a set theme, so default to auto
    setThemeIcon(theme);
    applyTheme(theme);
}

function setThemeIcon(theme) {
    const iconOptions = {
        light: "bi-sun",
        dark: "bi-moon-stars",
        auto: "bi-circle-half"
    }

    if (!Object.keys(iconOptions).includes(theme)) {
        throw new Error(`No icon for theme: ${theme}`);
    }

    $(".js-themeMenuBtn > i").removeClass(Object.values(iconOptions).join(" "));
    $(".js-themeMenuBtn > i").addClass(iconOptions[theme]);
}

function applyTheme(theme) {
    $('input[name="themeToggle"]').siblings("label").removeClass("active");
    $(`input[name="themeToggle"][value="${theme}"]`).siblings("label").addClass("active");

    if (!theme || theme === "auto") {
        theme = getPreferredTheme();
    }

    $("body").attr("data-bs-theme", theme);
}

function getCurrentDateTime() {
    var now = new Date();
    var year = now.getFullYear();
    var month = String(now.getMonth() + 1).padStart(2, '0');
    var day = String(now.getDate()).padStart(2, '0');
    var hours = String(now.getHours()).padStart(2, '0');
    var minutes = String(now.getMinutes()).padStart(2, '0');
    return `${year}-${month}-${day}T${hours}:${minutes}`;
}

// Sanitise a given string to remove HTML, making it DOM safe.
function sanitise(string) {
    if (typeof string !== "string") {
        return string;
    }

    const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#x27;',
        "/": '&#x2F;',
    };
    const reg = /[&<>"'/]/ig;
    return string.replace(reg, (match) => map[match]);
  }

$(document).ready(function() {
    // Activate all tooltips
    $('[data-bs-toggle="tooltip"]').tooltip();

    // Activate select2s
    $(".select-2").each(function() {
        $(this).select2({
            theme: "bootstrap",
            minimumResultsForSearch: 10
        });
    });

    $(".corbz-select").each(function() {
        $(this).initCorbzSelect();
    });

    $.notify.addStyle("bootstrap", {
        html: 
            '<div class="toast mt-3 overflow-hidden" role="alert">' +
                '<div class="toast-body">' +
                    '<span data-notify-text></span>' +
                '</div>' +
            "</div>"
    });

    $.notify.defaults({
        globalPosition: "bottom right",
        animationType: "fade",
        className: "success"
    });

    // Activate datepickers
    // $(".input-group.date").datepicker({format: "yyyy-mm-dd"});

    // Load theme
    initThemeChoice();
});

// Custom Select Jquery
(($) => {
    function initCorbzSelect() {
        const defaultSelectedHtml = "&nbsp;";

        const updateSelectedDisplay = ($select, $selected, $dropdown, settings) => {
            let values = $select.val() || [];
            let names = [];

            // if (settings.id === "styleTitleMutator") { debugger; }

            if (!Array.isArray(values)) { values = [values] };

            // Update names based on values
            $select.find("option").each(function() {
                if (values.includes($(this).val())) {
                    names.push($(this).text());
                }
            });

            const len = values.length;
            const total = $select.find("option").length;

            if (len === 0) { $selected.html(defaultSelectedHtml); }
            else if (len === total && total > 3) {$selected.text("All Selected")}
            else if (len > 3) { $selected.text(`${values.length} Selected`); }
            else { names ? $selected.text(names.join(", ")) : $selected.html(defaultSelectedHtml); }

            if (!settings.multiple) {
                $dropdown.find(".corbz-select-option").removeClass("active").each(function() {
                    if (names.includes($(this).data("name"))) {
                        $(this).addClass("active");
                    }
                });
            }

            $dropdown.find(".corbz-option-checkbox").each(function() {
                $(this).prop("checked", values.includes($(this).val()));
            });

        }

        this.each(function() {
            // The original select element, this will be hidden and replaced
            // with the custom input 'container'
            const $select = $(this);

            // The custom input to replace the original select
            const $container = $('<div class="corbz-select-container" tabindex="0">');

            // Contains text indicating the 'selected' options, acts as a
            // button to open the dropdown.
            const $selected = $('<div class="corbz-select-selected">');
            $selected.html(defaultSelectedHtml);

            // The dropdown box when accessing the container
            const $dropdown = $('<div class="corbz-select-dropdown">');

            // Search input to filter the dropdown results
            const $search = $('<input type="text" class="corbz-select-search" placeholder="Search ...">');

            const settings = {
                id: $select.prop("id"),
                multiple: $select.prop("multiple"),
                required: $select.prop("required"),
                disabled: $select.prop("disabled"),
                minResultsForSearch: 5
            }

            // Add custom elements to the DOM
            $dropdown.prepend($search);
            $container.append($selected).append($dropdown);
            $select.hide().after($container);

            // Show/Hide the dropdown when clicking the custom input
            $selected.on("click", function(event) {
                event.stopPropagation();
                $(".corbz-select-dropdown").not($dropdown).hide();
                $(".corbz-select-container").not($container).removeClass("active");
                $dropdown.toggle();
                $container.toggleClass("active", $dropdown.is(":visible"));
            });

            // Hide dropdown if clicking outside
            $(document).on('click', function() {
                $dropdown.hide();
                $container.removeClass("active");

                // Reset search filtering
                $search.val("");
                $search.trigger("keyup");
            });

            // Use or hide search
            $search.toggle($select.find("option").length > settings.minResultsForSearch);

            // Prevent closing the dropdown when selecting the search input
            $search.on("click", function (event) { event.stopPropagation(); });

            // Search to filter through options
            $search.on("keyup", function () {
                const searchValue = $(this).val().toLowerCase();
                $dropdown.find(".corbz-select-option").each(function() {
                    const optionText = $(this).text().toLowerCase();
                    $(this).toggle(optionText.includes(searchValue))
                })
            });

            const updateSelectedDisplayWrapper = () => {
                updateSelectedDisplay($select, $selected, $dropdown, settings)
            }

            const onOptionSelect = $option => {
                $dropdown.hide();
                $container.removeClass("active");
                $select.val($option.data("value"));
                updateSelectedDisplayWrapper();
            }

            $select.find("option").each(function() {
                const $option = $('<div class="corbz-select-option" tabindex="0">');
                $option.data("name", $(this).text());
                $option.data("value", $(this).val());
    
                if (!settings.multiple) {
                    $option.text($(this).text());
                    $option.on("click", () => onOptionSelect($option));
                }
                else {
                    const $checkbox = $(`<input type="checkbox" name="${settings.id}" class="corbz-option-checkbox" value="${$(this).val()}">`).val($(this).val());
                    const $label = $("<span>").text($(this).text());
                    $option.prepend($checkbox).append($label);
                    $option.on("click", function(event) {
                        event.stopPropagation();

                        // Handle if the user clicked inside the checkbox itself
                        if (!$(event.target).hasClass("corbz-option-checkbox")) {
                            $checkbox.prop("checked", !$checkbox.prop("checked"));
                        }

                        const selectedElems = $dropdown.find(`input[type="checkbox"][name="${settings.id}"]:checked`).map(function() {
                            return $(this).closest(".corbz-select-option");
                        });

                        // Get and internally set the selected values
                        const selectedVals = selectedElems.map(function() {
                            return this.data("value");
                        });
                        $select.val(selectedVals).trigger("change");

                        updateSelectedDisplayWrapper();
                    });
                }

                $dropdown.append($option)
            });

            // For no options, display a message
            if (!$select.find("option").length) {
                const $noOptions = $('<div class="corbz-select-text">');
                $noOptions.text("No options available");
                $dropdown.append($noOptions);
            }

            // Initialize display, and detect future changes
            updateSelectedDisplayWrapper();
            $select.on("change", updateSelectedDisplayWrapper);
        });
    }

    $.fn.initCorbzSelect = initCorbzSelect;

})(jQuery);
