/*!
 * @package     VP Prime Framework
 * @author      Abhishek Das <info@virtueplanet.com>
 * @link        https://www.virtueplanet.com
 * @copyright   Copyright (C) 2023-2025 Virtueplanet Services LLP. All Rights Reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

var MegaMenuModule = window.MegaMenuModule || {};

(function (mmm, document, window) {

    /**
     * Selectors and classes
     */
    mmm.topSelector = '.mod-megamenu';
    mmm.itemSelector = '.mod-megamenu--item';
    mmm.submenuSelector = '.mod-megamenu--sub';
    mmm.itemAnchorSelector = '.mod-megamenu--item-anchor';
    mmm.itemTitleSelector = '.mod-megamenu--item-title';
    mmm.dropdownSelector = '.mod-megamenu--container';
    mmm.firstLevelClass = 'mod-megamenu--level-1';
    mmm.groupClass = 'mod-megamenu--group';

    /**
     * Timers
     */
    mmm.initTimer = null;
    mmm.dropdownResizeTimer = {};

    /**
     * Initialise all mega menus.
     */
    mmm._init = function () {
        [].slice.call(document.querySelectorAll(mmm.topSelector)).forEach(function (menu) {
            mmm.initOne(menu);
        });
    }

    /**
     * Safe all initialise mega menus with debounce.
     */
    mmm.safeInit = function () {
        if (mmm.initTimer) {
            clearTimeout(mmm.initTimer);
        }

        mmm.initTimer = setTimeout(function () {
            mmm._init();
        }, 500);
    }

    /**
     * Initialise one mega menu.
     *
     * @param {Element} menu 
     */
    mmm.initOne = function (menu) {
        [].slice.call(menu.querySelectorAll(mmm.dropdownSelector)).forEach(function (dropdown) {
            // Add unique data id to each dropdown if not already present
            if (!dropdown.hasAttribute('data-mmm-uid')) {
                dropdown.setAttribute('data-mmm-uid', Math.random().toString(36).substring(2, 11));
            }

            mmm.setDropdownWidth(menu, dropdown);
        });
    }

    /**
     * Set dropdown width.
     *
     * @param {Element} menu      The mega menu element
     * @param {Element} dropdown   The dropdown element
     */
    mmm.setDropdownWidth = function (menu, dropdown) {
        var widthType = dropdown.getAttribute('data-mmm-drop-width');
        var uid = dropdown.getAttribute('data-mmm-uid');

        switch (widthType) {
            case 'auto':
                dropdown.setAttribute('data-mmm-dropdown-auto-resize', 'start');

                if (mmm.dropdownResizeTimer[uid]) {
                    clearTimeout(mmm.dropdownResizeTimer[uid]);
                }

                mmm.dropdownResizeTimer[uid] = setTimeout(function () {
                    mmm.adjustAutoWidth(menu, dropdown);
                }, 200);

                break;

            case 'custom':
                dropdown.style.left = '';
                dropdown.style.right = 'auto';

                if (dropdown.classList.contains(mmm.firstLevelClass)) {
                    mmm.setFirstLevelDropdownPosition(menu, dropdown, false);
                }
                break;

            case 'full_width':
                dropdown.style.left = '';
                dropdown.style.right = '';
                dropdown.style.width = '';

                var bodyBoundary = document.body.getBoundingClientRect();
                var dropdownBoundary = dropdown.getBoundingClientRect();
                var dropdownStyle = dropdown.currentStyle || window.getComputedStyle(dropdown);

                if (dropdown.classList.contains(mmm.firstLevelClass)) {
                    dropdown.style.left = (bodyBoundary.left - dropdownBoundary.left + parseFloat(dropdownStyle.marginLeft)) + 'px';
                    dropdown.style.width = (document.body.clientWidth - (parseFloat(dropdownStyle.marginRight) + parseFloat(dropdownStyle.marginLeft))) + 'px';
                } else {
                    dropdown.style.width = '100%';
                }
                break;
        }

    }

    /**
     * Adjust auto width.
     * 
     * @param {Element} menu      The mega menu element
     * @param {Element} dropdown  The dropdown element
     * 
     * @return {void}
     */
    mmm.adjustAutoWidth = function (menu, dropdown) {
        dropdown.setAttribute('data-mmm-dropdown-auto-resize', 'run');

        dropdown.style.width = '';
        dropdown.style.left = '';
        dropdown.style.right = '';

        if (dropdown.parentElement.classList.contains(mmm.groupClass)) {
            dropdown.style.width = 'auto';
        } else if (dropdown.querySelector(mmm.submenuSelector).style.getPropertyValue('--megamenu-item-direction') === 'row') {
            dropdown.classList.add('mod-megamenu-test-width');

            dropdown.style.width = (dropdown.offsetWidth + 2) + 'px';

            [].slice.call(dropdown.querySelectorAll(mmm.itemAnchorSelector)).forEach(function (anchor) {
                let loopCounter = 0;

                if (dropdown.getAttribute('data-mmm-dropdown-auto-resize') === 'run') {
                    while (mmm.isOverflown(anchor) && dropdown.getAttribute('data-mmm-dropdown-auto-resize') === 'run') {
                        loopCounter++;

                        if (loopCounter > 300) {
                            console.warn('Mega Menu: Auto width adjustment loop exceeded 300 iterations. Breaking out to prevent infinite loop.', dropdown);
                            break;
                        }

                        var overflowAmount = mmm.getOverflowAmount(anchor);
                        overflowAmount = overflowAmount < 0 ? 0 : overflowAmount;
                        var increment = Math.max(Math.ceil(overflowAmount / 5), 1);

                        dropdown.style.width = (dropdown.offsetWidth + increment + 2) + 'px';
                    }
                }
            });

            dropdown.classList.remove('mod-megamenu-test-width');
        }

        if (dropdown.classList.contains(mmm.firstLevelClass)) {
            mmm.setFirstLevelDropdownPosition(menu, dropdown, true);
        }

        dropdown.setAttribute('data-mmm-dropdown-auto-resize', 'done');
    }

    /**
     * Set first level dropdown position.
     *
     * @param {Element} menu 
     * @param {Element} dropdown 
     */
    mmm.setFirstLevelDropdownPosition = function (menu, dropdown, adjustWidth = false) {
        var menuBoundary = menu.getBoundingClientRect();
        var dropdownBoundary = dropdown.getBoundingClientRect();

        if (dropdownBoundary.right > menuBoundary.right) {
            var diff = dropdownBoundary.right - menuBoundary.right;
            var leftSpace = dropdownBoundary.left - menuBoundary.left;

            if (diff > 0) {

                if (leftSpace > diff) {
                    dropdown.style.left = (diff * -1) + 'px';
                } else if (leftSpace > 0) {
                    dropdown.style.left = (leftSpace * -1) + 'px';

                    if (adjustWidth) {
                        dropdown.style.width = dropdown.offsetWidth - (diff - leftSpace) + 'px';
                    }
                }
            }

        }
    }

    /**
     * Check if element is overflown.
     * 
     * @param {Element} element
     * 
     * @returns {boolean}
     */
    mmm.isOverflown = function (element) {
        return element.scrollWidth > element.clientWidth;
    }

    /**
     * Get overflow amount.
     * 
     * @param {Element} element
     *
     * @returns {number}
     */
    mmm.getOverflowAmount = function (element) {
        return element.scrollWidth - element.clientWidth;
    }

    document.addEventListener('DOMContentLoaded', function (event) {
        mmm.safeInit();
    })

    window.addEventListener('load', function () {
        mmm.safeInit();
    });

    window.addEventListener('resize', function () {
        mmm.safeInit();
    })

})(MegaMenuModule, document, window);
