{% comment %}
Main Tom Select template.

Context Variables:
- widget: Contains configuration, plugin settings, URLs, selected items, etc.

Blocks:
- block select_element: Override to change the way the <select> is included.
- block tomselect_init: Override to alter the TomSelect initialization logic, including event handlers, fetch calls, and callback methods.
- block tomselect_plugins: Insert or override plugin-related JS configuration.
- block tomselect_url_setup: Define the originalFirstUrl function for constructing the initial URL.
- block tomselect_config: Define the main TomSelect configuration object.
- block tomselect_render: Define the render object for customizing the appearance of options, items, and other elements.
- block tomselect_extra_js: Add custom JS at the end of initialization.

Overriding Example:
To override only the plugin configuration, you might create:
`django_tomselect/tomselect.html`:

    {% block tomselect_plugins %}
        // Your custom plugin code here
    {% endblock tomselect_plugins %}

This will append your changes to the default configuration.

To completely replace initialization logic, you could:

    {% block tomselect_init %}
        // Your entirely custom initialization code here
    {% endblock tomselect_init %}

This will replace the original code block if you use `{% block ... %}{% endblock ... %}` without super.

You can also extend and call `{{ block.super }}` to augment existing logic.
{% endcomment %}

{% load i18n %}

{% block select_element %}
    {% include "django_tomselect/render/select.html" with widget=widget %}
{% endblock select_element %}

<script>
    {% block tomselect_global_setup %}
    {% endblock tomselect_global_setup %}
</script>

<script>
    {% block tomselect_init %}
        (function() {
            const elementId = '{% if "id" in widget.attrs.keys and widget.attrs.id %}{{ widget.attrs.id }}{% else %}{{ widget.name }}{% endif %}';
            const element = document.getElementById(elementId);
            if (!element) return;

            // Create a unique reset variable name based on the element ID
            const resetVarName = 'wasReset_' + elementId.replace(/-/g, '_');
            window[resetVarName] = false;

            // Used for resetting the TomSelect contents when a query is zeroed
            let previousQuery = '';

            function logCallback(data) {
                console.log("%c Received callback data:", "color:red;", data);
            }

            // Helper function to reset TomSelect state
            function resetTomSelectState(tomSelect, originalFirstUrl) {
                if (!tomSelect) return;
                
                tomSelect.clearOptions();
                tomSelect.clearCache();
                tomSelect.settings.pagination = {};

                if (tomSelect.dropdown_content) {
                    tomSelect.dropdown_content.scrollTop = 0;
                }

                tomSelect.settings.firstUrl = originalFirstUrl;
                tomSelect.settings.setNextUrl = originalFirstUrl;
                tomSelect.clearPagination();
                tomSelect.load('', logCallback);
                
                // Mark the widget as reset
                window[resetVarName] = true;
            }

            // Helper function to add a URL parameter
            function addUrlParam(url, paramName, paramValue) {
                return `${url}&${paramName}=${encodeURIComponent(paramValue)}`;
            }

            {% block tomselect_url_setup %}
                // Constructing the originalFirstUrl function based on query and filters
                var originalFirstUrl = function(query) {
                    var url = '{{ widget.autocomplete_url }}' + '?q=' + encodeURIComponent(query){% if 'autocomplete_params' in widget.keys and not widget.autocomplete_params == "" %} + '&{{ widget.autocomplete_params|safe }}'{% endif %};
                    
                    {% if "dependent_field" in widget.keys %}
                        const dependentField = document.getElementById('id_{{ widget.dependent_field }}');
                        const dependentValue = dependentField ? dependentField.value : '';
                        url = addUrlParam(url, "f", `'{{ widget.dependent_field }}__{{ widget.dependent_field_lookup }}=${dependentValue}'`);
                    {% endif %}
                    
                    {% if "exclude_field" in widget.keys %}
                        const excludeField = document.getElementById('id_{{ widget.exclude_field }}');
                        const excludeValue = excludeField ? excludeField.value : '';
                        url = addUrlParam(url, "e", `'{{ widget.exclude_field }}__{{ widget.exclude_field_lookup }}=${excludeValue}'`);
                    {% endif %}
                    
                    return url;
                };
            {% endblock tomselect_url_setup %}

            {% block tomselect_config %}
                const config = {
                    valueField: '{{ widget.value_field }}',
                    labelField: '{{ widget.label_field }}',
                    searchField: [],
                    highlight: {{ widget.highlight|yesno:"true,false" }},
                    openOnFocus: {{ widget.open_on_focus|yesno:"true,false" }},
                    hideSelected: {{ widget.hide_selected|yesno:"true,false" }},
                    maxOptions: {% if widget.max_options %}{{ widget.max_options }}{% else %}null{% endif %},
                    preload: {% if widget.preload == "focus" %}'focus'{% elif widget.preload %}true{% else %}false{% endif %},
                    maxItems: {% if not widget.is_multiple %}1{% else %}{% if widget.max_items %}{{ widget.max_items }}{% else %}null{% endif %}{% endif %},
                    showValueField: {% if 'dropdown_header' in widget.plugins.keys and widget.plugins.dropdown_header.show_value_field %}true{% else %}false{% endif %},
                    create: {% if 'create' in widget.keys and widget.create %}true{% else %}false{% endif %},
                    resetVarName: resetVarName,
                    originalFirstUrl: originalFirstUrl,
                    {% if "dependent_field" in widget.keys %}
                        dependentField: 'id_{{ widget.dependent_field }}',
                    {% endif %}
                    {% if "exclude_field" in widget.keys %}
                        excludeField: 'id_{{ widget.exclude_field }}',
                    {% endif %}

                    {% block tomselect_plugins %}
                        plugins: {
                            {% if 'checkbox_options' in widget.plugins.keys and widget.plugins.checkbox_options %}
                                checkbox_options: true,
                            {% endif %}

                            {% if 'clear_button' in widget.plugins.keys %}
                                clear_button: {
                                    title: '{{ widget.plugins.clear_button.title }}',
                                    className: '{{ widget.plugins.clear_button.class_name }}'
                                },
                            {% endif %}

                            {% if 'dropdown_header' in widget.plugins.keys %}
                                dropdown_header:{
                                    title: '{% if widget.plugins.dropdown_header.title %}{{ widget.plugins.dropdown_header.title }}{% else %}Select an option{% endif %}',
                                    headerClass: '{{ widget.plugins.dropdown_header.header_class }}',
                                    {% include "django_tomselect/render/dropdown_header.html" with widget=widget %}
                                },
                            {% endif %}

                            {% if 'dropdown_footer' in widget.plugins.keys %}
                                dropdown_footer:{
                                    title: '{% if widget.plugins.dropdown_footer.title %}{{ widget.plugins.dropdown_footer.title }}{% else %}Select an option{% endif %}',
                                    footerClass: '{{ widget.plugins.dropdown_footer.footer_class }}',
                                    {% include "django_tomselect/render/dropdown_footer.html" with widget=widget %}
                                },
                            {% endif %}

                            {% if 'dropdown_input' in widget.plugins.keys and widget.plugins.dropdown_input %}
                                dropdown_input: true,
                            {% endif %}

                            {% if 'remove_button' in widget.plugins.keys %}
                                remove_button: {
                                    title: '{{ widget.plugins.remove_button.title }}',
                                    label: '{{ widget.plugins.remove_button.label|safe }}',
                                    className: '{{ widget.plugins.remove_button.class_name }}'
                                },
                            {% endif %}

                            virtual_scroll: true
                        },
                    {% endblock tomselect_plugins %}

                    onInitialize: function() {
                        {% if widget.value %}
                            // Prepare all options in a single batch
                            const allOptions = {};
                            const allItems = [];
                    
                            {% for option in widget.selected_options %}
                                allOptions['{{ option.value }}'] = {
                                    {{ widget.value_field }}: '{{ option.value }}',
                                    {{ widget.label_field }}: '{{ option.label }}',
                                    {% if "create_url" in option.keys %}create_url: '{{ option.create_url }}',{% endif %}
                                    {% if "detail_url" in option.keys %}detail_url: '{{ option.detail_url }}',{% endif %}
                                    {% if "update_url" in option.keys %}update_url: '{{ option.update_url }}',{% endif %}
                                    {% if "delete_url" in option.keys %}delete_url: '{{ option.delete_url }}',{% endif %}
                                };
                                allItems.push('{{ option.value }}');
                            {% endfor %}
                    
                            // Add all options at once
                            this.addOptions(allOptions);
                    
                            // Use TomSelect's built-in setValue with silent=true
                            this.setValue(allItems, true);
                        {% endif %}
                    },

                    onBlur: function() {
                        const tomSelect = element.tomselect;
                        resetTomSelectState(tomSelect, originalFirstUrl);

                        // Continue with the default tomselect blur functionality
                        if (document.hasFocus() === false)
                            return;
                        var self = this;
                        if (!self.isFocused)
                            return;
                        self.isFocused = false;
                        self.ignoreFocus = false;
                        var deactivate = () => {
                            self.close();
                            self.setActiveItem();
                            self.setCaret(self.items.length);
                        };
                        deactivate();
                    },

                    shouldLoad: function(query){
                        var shouldLoadValue;
                        if (this.settings.page && (!query.trim() || query === undefined)) {
                            shouldLoadValue = true;
                        } else {
                            shouldLoadValue = query.length >= {{ widget.minimum_query_length }};
                        }

                        if (previousQuery.length > 0 && (!query.trim() || query === undefined)) {
                            const tomSelect = element.tomselect;
                            resetTomSelectState(tomSelect, originalFirstUrl);
                        }

                        previousQuery = query;
                        return shouldLoadValue;
                    },

                    firstUrl: originalFirstUrl,

                    getUrl: function(query) {
                        var url = this.settings.pagination[query] || this.settings.firstUrl(query);
                        return url;
                    },

                    load: function(query, callback) {
                        var self = this;
                        var url = this.getUrl(query);
                        if (window[resetVarName] === true) {
                            url = originalFirstUrl(query);
                        }

                        var currentPage = 1;

                        // Helper function to check if all items are already selected and load more if needed
                        const checkAndLoadMore = function(json, originalCallback, collectedResults = []) {
                            // Store the pagination info for virtual scrolling regardless of selection status
                            if (json.has_more && json.next_page) {
                                let baseUrl = url.replace(/&p=\d+/g, '');
                                if (!self.settings.pagination) {
                                    self.settings.pagination = {};
                                }

                                // Update the pagination URL for this query
                                self.settings.pagination[query] = baseUrl + '&p=' + json.next_page;
                            }

                            // If no results at all, return empty array
                            if (!json.results || json.results.length === 0) {
                                return originalCallback(collectedResults);
                            }

                            // Filter out already selected items
                            const newResults = json.results.filter(item =>
                                !self.items.includes(String(item[self.settings.valueField])));

                            // Add new unselected results to our collection
                            collectedResults = collectedResults.concat(newResults);

                            // Set the current page
                            currentPage = json.page;

                            // Check if all items in the response were already selected and we need more
                            const allSelected = newResults.length === 0;
                            const needMoreItems = collectedResults.length < 20; // Ensure we have a minimum set of items to show

                            // Use the pagination metadata to determine if we should continue auto-loading
                            if ((allSelected || needMoreItems) && json.has_more && json.next_page && json.page < json.total_pages) {
                                // All items are already selected, and there are more pages
                                const nextPageUrl = self.settings.pagination[query]; // Use the stored URL

                                // Fetch the next page
                                fetch(nextPageUrl)
                                    .then(response => response.json())
                                    .then(nextJson => checkAndLoadMore(nextJson, originalCallback, collectedResults))
                                    .catch(error => {
                                        console.error("Error loading next page:", error);
                                        originalCallback(collectedResults);
                                    });
                            } else {
                                // Either we found enough unselected items, reached the end, or total pages
                                originalCallback(collectedResults);
                            }
                        };

                        // Main fetch call
                        fetch(url)
                            .then(response => response.json())
                            .then(json => {
                                // Temporarily disable scroll behavior for performance
                                const _scrollToOption = this.scrollToOption;
                                this.scrollToOption = () => {};

                                // Start the check-and-load process
                                checkAndLoadMore(json, result => {
                                    callback(result);

                                    // Set next url
                                    if (json.total_pages > currentPage) {
                                        url = url.replace(/&p=\d+/g, '');
                                        this.setNextUrl(query, url + '&p=' + (currentPage + 1));
                                    }

                                    // If window[resetVarName] is true, we need to reset the page and set back to false
                                    if (window[resetVarName] === true) {
                                        window[resetVarName] = false;
                                        this.setNextUrl(query, url + '&p=1');
                                    }

                                    // Restore scrollToOption after the callback
                                    this.scrollToOption = _scrollToOption;
                                }, []);
                            })
                            .catch(error => {
                                console.error(`Error loading data: '${error}' with url: ${url}`);
                                callback([]);
                            });
                    },

                    {% block tomselect_render %}
                        render: {
                            {% include "django_tomselect/render/item.html" with widget=widget %}
                            {% include "django_tomselect/render/option.html" with widget=widget %}
                            {% include "django_tomselect/render/loading.html" with widget=widget %}
                            {% include "django_tomselect/render/loading_more.html" with widget=widget %}
                            {% include "django_tomselect/render/no_more_results.html" with widget=widget %}
                            {% include "django_tomselect/render/no_results.html" with widget=widget %}
                            {% include "django_tomselect/render/not_loading.html" with widget=widget %}
                            {% include "django_tomselect/render/optgroup_header.html" with widget=widget %}
                            {% include "django_tomselect/render/optgroup.html" with widget=widget %}
                            {% if 'create' in widget.keys and widget.create %}
                                {% include "django_tomselect/render/option_create.html" with widget=widget %}
                            {% endif %}
                        }
                    {% endblock tomselect_render %}

                };
            {% endblock tomselect_config %}

            {% if 'render' in widget.attrs.keys and widget.attrs.render %}
                element.addEventListener('option_add', function() {
                    // Ensure all selected data is preserved
                    this.items.forEach(item => {
                        this.options[item].selected = true;
                    });
                });

                element.addEventListener('load', function(data) {
                    // Ensure all loaded data is preserved
                    data.forEach(item => {
                        this.options[item.id] = item;
                    });
                });
            {% endif %}

            // Mark the select as a TomSelect widget
            element.setAttribute('data-tomselect', 'true');

            {% if not widget.use_htmx %}
                document.addEventListener('DOMContentLoaded', () => {
                    window.djangoTomSelect.initialize(element, config);
                });
            {% else %}
                window.djangoTomSelect.initialize(element, config);
            {% endif %}
        })();
    {% endblock tomselect_init %}

    {% block tomselect_extra_js %}{% endblock tomselect_extra_js %}
</script>