/**
 * @package         Regular Labs Library
 * @version         24.6.22903
 * 
 * @author          Peter van Westen <info@regularlabs.com>
 * @link            https://regularlabs.com
 * @copyright       Copyright © 2024 Regular Labs All Rights Reserved
 * @license         GNU General Public License version 2 or later
 */

(function() {
    'use strict';

    window.RegularLabs = window.RegularLabs || {};

    window.RegularLabs.TreeSelect = window.RegularLabs.TreeSelect || {
        direction: (document.dir !== undefined) ? document.dir : document.getElementsByTagName("html")[0].getAttribute("dir"),

        init: function(id) {
            const menu = document.querySelector('div#rl-treeselect-' + id);

            if ( ! menu) {
                return;
            }

            const list             = menu.querySelector('ul');
            const top_level_items  = list.querySelectorAll(':scope > li');
            const items            = list.querySelectorAll('li');
            const search_field     = menu.querySelector('[name="treeselectfilter"]');
            const sub_tree_select  = menu.querySelector('div.sub-tree-select > *');
            const no_results_found = menu.querySelector('joomla-alert');

            items.forEach((item) => {
                // Store the innerText for filtering
                // because if done later, also the text from added menus and buttons is added
                item.text = item.innerText;
            });

            items.forEach((item) => {
                const checkbox = item.querySelector(':scope > .treeselect-item > input');

                if ( ! checkbox) {
                    return;
                }

                item.classList.toggle('rl-item-checked', checkbox.checked);

                checkbox.addEventListener('change', () => {
                    item.classList.toggle('rl-item-checked', checkbox.checked);
                });

                const child_list = item.querySelector(':scope > ul.treeselect-sub');

                if ( ! child_list) {
                    return;
                }

                const label = item.querySelector('label');

                const sub_tree_select_el = sub_tree_select.cloneNode(true);

                const sub_tree_expand     = document.createElement('span');
                sub_tree_expand.className = 'treeselect-toggle icon-chevron-down';
                sub_tree_expand.collapsed = false;

                sub_tree_expand.addEventListener('click', () => {
                    this.expand(child_list, sub_tree_expand);
                });

                sub_tree_select_el.querySelector('[data-action="checkNested"]').addEventListener('click', () => {
                    this.check(child_list, true);
                });

                sub_tree_select_el.querySelector('[data-action="uncheckNested"]').addEventListener('click', () => {
                    this.check(child_list, false);
                });

                sub_tree_select_el.querySelector('[data-action="toggleNested"]').addEventListener('click', () => {
                    this.check(child_list, 'toggle');
                });

                if (checkbox.dataset['rlTreeselectCollapseChildren']) {
                    // Collapse children if top level parent is selected
                    if (checkbox.checked) {
                        sub_tree_expand.collapsed = false;
                        this.expand(child_list, sub_tree_expand);
                        this.check(child_list, false);
                    }

                    // Add event when (un)checking top level parent
                    checkbox.addEventListener('click', () => {
                        sub_tree_expand.collapsed = ! checkbox.checked;
                        this.expand(child_list, sub_tree_expand);
                        this.check(child_list, false);
                    });
                }

                item.insertBefore(sub_tree_expand, item.firstChild);
                label.append(sub_tree_select_el);
            });

            menu.querySelector('[data-action="checkAll"]').addEventListener('click', () => {
                this.check(menu, true);
            });
            menu.querySelector('[data-action="uncheckAll"]').addEventListener('click', () => {
                this.check(menu, false);
            });
            menu.querySelector('[data-action="toggleAll"]').addEventListener('click', () => {
                this.check(menu, 'toggle');
            });

            menu.querySelector('[data-action="expandAll"]').addEventListener('click', () => {
                top_level_items.forEach((item) => {
                    const child_list      = item.querySelector('ul.treeselect-sub');
                    const sub_tree_expand = item.querySelector('.treeselect-toggle');
                    if ( ! child_list || ! sub_tree_expand) {
                        return;
                    }
                    sub_tree_expand.collapsed = true;
                    this.expand(child_list, sub_tree_expand);
                });
            });

            menu.querySelector('[data-action="collapseAll"]').addEventListener('click', () => {
                top_level_items.forEach((item) => {
                    const child_list      = item.querySelector('ul.treeselect-sub');
                    const sub_tree_expand = item.querySelector('.treeselect-toggle');
                    if ( ! child_list || ! sub_tree_expand) {
                        return;
                    }
                    sub_tree_expand.collapsed = false;
                    this.expand(child_list, sub_tree_expand);
                });
            });
            menu.querySelector('[data-action="showAll"]').addEventListener('click', () => {
                this.resetSearch(items, search_field, no_results_found);
            });
            menu.querySelector('[data-action="showSelected"]').addEventListener('click', (e) => {
                this.resetSearch(items, search_field, no_results_found, true);
            });

            // Takes care of the filtering
            search_field.addEventListener('keyup', () => {
                this.doSearch(items, search_field, no_results_found);
            });
        },

        resetSearch: function(items, search_field, no_results_found, has_checked) {
            search_field.value = '';
            this.doSearch(items, search_field, no_results_found, has_checked);
        },

        doSearch: function(items, search_field, no_results_found, has_checked) {
            const text = search_field.value.toLowerCase();

            no_results_found.style.display = 'none';

            let results_found = 0;

            items.forEach((item) => {
                if (has_checked && ! item.querySelector('input:checked')) {
                    item.style.display = 'none';
                    return;
                }

                if (text !== '') {
                    let item_text = item.text.toLowerCase();
                    item_text     = item_text.replace(/\s+/g, ' ').trim();

                    if (item_text.indexOf(text) == -1) {
                        item.style.display = 'none';
                        return;
                    }
                }

                results_found++;
                item.style.display = 'block';
            });

            if ( ! results_found) {
                no_results_found.style.display = 'block';
            }
        },

        check: function(parent, checked) {
            const items = parent.querySelectorAll('li');

            items.forEach((item) => {
                if (item.style.display === 'none') {
                    return;
                }

                const checkbox = item.querySelector(':scope > .treeselect-item input:enabled');

                if ( ! checkbox) {
                    return;
                }

                checkbox.checked = checked === 'toggle' ? ! checkbox.checked : checked;

                item.classList.toggle('rl-item-checked', checked);
            });
        },

        expand: function(element, button) {
            const show = button.collapsed;

            element.style.display = show ? 'block' : 'none';

            button.classList.toggle('icon-chevron-down', show);
            button.classList.toggle(this.direction === 'rtl' ? 'icon-chevron-left' : 'icon-chevron-right', ! show);

            button.collapsed = ! button.collapsed;

            if ( ! show) {
                return;
            }

            const child_lists = element.querySelectorAll(':scope > li > ul.treeselect-sub');

            if ( ! child_lists.length) {
                return;
            }

            child_lists.forEach((child_list) => {
                const child_button     = child_list.closest('li').querySelector('.treeselect-toggle');
                child_button.collapsed = true;
                this.expand(child_list, child_button);
            });

        }
    };
})();
