/**
 * RSL Adaptive Density Mode
 *
 * Automatically adjusts spacing and density based on pointer type (touch vs mouse),
 * viewport size, and user preferences. Provides adaptive UI that optimizes for
 * the current input method while allowing manual overrides.
 *
 * @fileoverview Adaptive density system with automatic device detection
 * @version 1.0.0
 * @license MIT
 *
 * Key Features:
 * - Auto-detects pointer type (coarse/fine)
 * - Three density levels: compact, standard, spacious
 * - Manual override support via data attributes or API
 * - Hybrid device support (devices with both touch and mouse)
 * - MutationObserver for dynamic content
 * - CSS class and data attribute application
 *
 * Usage:
 * // Automatic (no code required):
 * <div class="slot-layout">...</div>
 *
 * // Manual override:
 * <div class="slot-layout" data-rsl-density="spacious">...</div>
 *
 * // JavaScript API:
 * RSL.Density.set(element, 'compact');
 * RSL.Density.get(element);
 * RSL.Density.reset(element);
 *
 * Public API:
 * - RSL.Density.init() - Initialize/reinitialize density
 * - RSL.Density.set(element, level) - Set density for element
 * - RSL.Density.reset(element) - Reset to auto-detection
 * - RSL.Density.get(element) - Get current density
 * - RSL.Density.detectPointer() - Get pointer type
 * - RSL.Density.levels - Available density levels
 */

(function() {
    'use strict';

    // Initialize RSL namespace
    window.RSL = window.RSL || {};

    /**
     * Available density levels
     * @const
     * @type {Object<string, string>}
     */
    const DENSITY_LEVELS = {
        COMPACT: 'compact',    // Tight spacing for mouse/desktop users
        STANDARD: 'standard',  // Balanced spacing
        SPACIOUS: 'spacious'   // Generous spacing for touch/mobile users
    };

    /** @const {string} Data attribute for density level */
    const DENSITY_ATTRIBUTE = 'data-rsl-density';

    /** @const {string} Data attribute marking manual override */
    const MANUAL_DENSITY_ATTRIBUTE = 'data-rsl-density-manual';

    /**
     * Detect the current pointer type using CSS media queries
     *
     * Uses the pointer media query to determine if the primary input
     * mechanism is coarse (touch) or fine (mouse/trackpad). Falls back
     * to touch capability detection for older browsers.
     *
     * @returns {string} 'coarse' for touch devices, 'fine' for mouse/trackpad, or 'none'
     *
     * @example
     * const pointerType = detectPointerType();
     * if (pointerType === 'coarse') {
     *   // Apply spacious layout for touch
     * }
     */
    function detectPointerType() {
        // Check CSS media query for pointer capability (preferred method)
        if (window.matchMedia) {
            if (window.matchMedia('(pointer: coarse)').matches) {
                return 'coarse'; // Touch devices (tablets, phones)
            }
            if (window.matchMedia('(pointer: fine)').matches) {
                return 'fine'; // Mouse, trackpad, stylus
            }
        }

        // Fallback: check for touch capability
        if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
            return 'coarse';
        }

        return 'fine'; // Default to fine pointer
    }

    /**
     * Get the recommended density level based on pointer type
     *
     * Maps pointer types to appropriate density levels:
     * - Coarse (touch) → Spacious (larger hit targets)
     * - Fine (mouse) → Compact (efficient space usage)
     * - Unknown → Standard (balanced)
     *
     * @param {string} pointerType - 'coarse', 'fine', or 'none'
     * @returns {string} Recommended density level from DENSITY_LEVELS
     *
     * @example
     * const density = getRecommendedDensity('coarse');
     * // returns 'spacious'
     */
    function getRecommendedDensity(pointerType) {
        switch (pointerType) {
            case 'coarse':
                return DENSITY_LEVELS.SPACIOUS; // Touch needs more space
            case 'fine':
                return DENSITY_LEVELS.COMPACT; // Mouse can handle tighter spacing
            default:
                return DENSITY_LEVELS.STANDARD; // Fallback
        }
    }

    /**
     * Check if element has a manual density override
     *
     * Checks both data-rsl-density-manual and data-rsl-density attributes.
     * If either is set to a valid density level, it's considered a manual override.
     *
     * @param {HTMLElement} element - Element to check
     * @returns {string|null} Manual density level or null if auto-detection should be used
     *
     * @example
     * <div data-rsl-density="spacious">...</div>
     * getManualDensity(element); // returns 'spacious'
     */
    function getManualDensity(element) {
        // Check for explicit manual override attribute
        const manualDensity = element.getAttribute(MANUAL_DENSITY_ATTRIBUTE);
        if (manualDensity && Object.values(DENSITY_LEVELS).includes(manualDensity)) {
            return manualDensity;
        }

        // Check for explicit data-rsl-density attribute (treat as manual)
        const explicitDensity = element.getAttribute(DENSITY_ATTRIBUTE);
        if (explicitDensity && Object.values(DENSITY_LEVELS).includes(explicitDensity)) {
            return explicitDensity;
        }

        return null;
    }

    /**
     * Apply density level to an element
     *
     * Sets both data attribute and CSS class for maximum compatibility.
     * Removes old density classes before applying new one.
     *
     * @param {HTMLElement} element - Target element
     * @param {string} density - Density level from DENSITY_LEVELS
     *
     * @example
     * applyDensity(element, 'spacious');
     * // Adds: data-rsl-density="spacious" and class="rsl-density-spacious"
     */
    function applyDensity(element, density) {
        // Set data attribute for CSS selectors
        element.setAttribute(DENSITY_ATTRIBUTE, density);

        // Remove old density classes
        Object.values(DENSITY_LEVELS).forEach(level => {
            element.classList.remove(`rsl-density-${level}`);
        });

        // Add new density class for easier CSS targeting
        element.classList.add(`rsl-density-${density}`);
    }

    /**
     * Initialize density for all qualifying layout elements
     *
     * Finds all slot layouts, containers, and sidebar layouts, then applies
     * appropriate density based on pointer type or manual overrides.
     * Respects existing manual settings.
     *
     * @public
     *
     * @example
     * // Called automatically on DOMContentLoaded
     * // Can be called manually after dynamic content changes:
     * RSL.Density.init();
     */
    function initDensityMode() {
        const pointerType = detectPointerType();
        const recommendedDensity = getRecommendedDensity(pointerType);

        // Find all elements that should have density applied
        const elements = document.querySelectorAll(`
            .slot-layout,
            .nested-slot-layout,
            .responsive-slot-layout,
            .container,
            .container-fluid,
            .rsl-sidebar-layout
        `);

        elements.forEach(element => {
            // Check if user has set manual density
            const manualDensity = getManualDensity(element);

            if (manualDensity) {
                // Respect manual override
                applyDensity(element, manualDensity);
            } else if (!element.hasAttribute(DENSITY_ATTRIBUTE)) {
                // Only apply auto-density if not already set
                applyDensity(element, recommendedDensity);
            }
        });
    }

    /**
     * Manually set density for a specific element
     *
     * Overrides auto-detection and sets a specific density level.
     * Marks element as manually configured to prevent auto-updates.
     *
     * @param {HTMLElement} element - Target element
     * @param {string} density - Density level: 'compact', 'standard', or 'spacious'
     *
     * @example
     * const container = document.querySelector('.slot-layout');
     * RSL.Density.set(container, 'spacious');
     */
    function setDensity(element, density) {
        if (!Object.values(DENSITY_LEVELS).includes(density)) {
            console.warn('Invalid density level:', density);
            return;
        }

        applyDensity(element, density);
        // Mark as manual override so auto-detection doesn't change it
        element.setAttribute(MANUAL_DENSITY_ATTRIBUTE, density);
    }

    /**
     * Reset element to auto-detect density mode
     *
     * Removes manual override and re-applies density based on current
     * pointer type detection.
     *
     * @param {HTMLElement} element - Element to reset
     *
     * @example
     * RSL.Density.reset(container);
     * // Now uses auto-detected density based on pointer type
     */
    function resetDensity(element) {
        element.removeAttribute(MANUAL_DENSITY_ATTRIBUTE);
        const pointerType = detectPointerType();
        const recommendedDensity = getRecommendedDensity(pointerType);
        applyDensity(element, recommendedDensity);
    }

    /**
     * Get current density level of an element
     *
     * @param {HTMLElement} element - Element to query
     * @returns {string} Current density level or 'standard' if not set
     *
     * @example
     * const currentDensity = RSL.Density.get(container);
     * console.log(currentDensity); // 'compact', 'standard', or 'spacious'
     */
    function getDensity(element) {
        return element.getAttribute(DENSITY_ATTRIBUTE) || DENSITY_LEVELS.STANDARD;
    }

    /**
     * Listen for pointer type changes on hybrid devices
     *
     * Some devices (2-in-1 laptops, tablets with keyboards) can switch
     * between touch and mouse input. This listener detects those changes
     * and updates density accordingly.
     */
    if (window.matchMedia) {
        const coarseQuery = window.matchMedia('(pointer: coarse)');
        const fineQuery = window.matchMedia('(pointer: fine)');

        /**
         * Handle pointer type change events
         * Re-initializes density for elements without manual overrides
         */
        const handlePointerChange = () => {
            initDensityMode();
        };

        // Modern browsers
        if (coarseQuery.addEventListener) {
            coarseQuery.addEventListener('change', handlePointerChange);
            fineQuery.addEventListener('change', handlePointerChange);
        }
        // Fallback for older browsers
        else if (coarseQuery.addListener) {
            coarseQuery.addListener(handlePointerChange);
            fineQuery.addListener(handlePointerChange);
        }
    }

    /**
     * Public API
     *
     * Exposed methods for density management
     *
     * @namespace RSL.Density
     * @property {Function} init - Initialize/reinitialize density
     * @property {Function} set - Set density for element
     * @property {Function} reset - Reset to auto-detection
     * @property {Function} get - Get current density
     * @property {Object} levels - Available density levels
     * @property {Function} detectPointer - Get pointer type
     */
    window.RSL.Density = {
        init: initDensityMode,
        set: setDensity,
        reset: resetDensity,
        get: getDensity,
        levels: DENSITY_LEVELS,
        detectPointer: detectPointerType
    };

    /**
     * Auto-initialize on DOM ready or immediately if already loaded
     */
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initDensityMode);
    } else {
        initDensityMode();
    }

    /**
     * Observe DOM for dynamically added layouts
     *
     * Uses MutationObserver to automatically apply density to layouts
     * that are added to the DOM after initial page load (e.g., via AJAX,
     * dynamic rendering, SPAs).
     */
    if (window.MutationObserver) {
        const observer = new MutationObserver(mutations => {
            let shouldUpdate = false;

            mutations.forEach(mutation => {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) { // Element node
                        if (node.matches && node.matches('.slot-layout, .responsive-slot-layout, .nested-slot-layout')) {
                            shouldUpdate = true;
                        }
                    }
                });
            });

            if (shouldUpdate) {
                initDensityMode();
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

})();
