/**
 * RSL Form Elements System
 *
 * Provides interactive form components with custom styling and behavior including
 * sliders with live value display, custom select dropdowns with keyboard navigation,
 * file upload tiles with visual feedback, and theming via data attributes.
 *
 * @fileoverview Interactive form components with accessibility support
 * @version 1.0.0
 * @license MIT
 *
 * Key Features:
 * - Custom select dropdowns with full keyboard navigation (Arrow keys, Enter, Escape)
 * - Slider inputs with synchronized value display
 * - File upload tiles with keyboard support and filename display
 * - Data attribute theming system for custom colors and styles
 * - ARIA attributes for screen reader accessibility
 * - Focus management and visual feedback
 *
 * Usage:
 * // Slider with live value:
 * <div class="rsl-slider">
 *   <input type="range" class="rsl-slider-input" min="0" max="100" value="50">
 *   <span class="rsl-slider-value">50%</span>
 * </div>
 *
 * // Custom select:
 * <div class="rsl-select">
 *   <button class="rsl-select-toggle" aria-haspopup="listbox" aria-expanded="false">
 *     <span class="rsl-select-value">Choose...</span>
 *   </button>
 *   <ul class="rsl-select-list" role="listbox" hidden>
 *     <li class="rsl-select-option" role="option" data-value="1">Option 1</li>
 *   </ul>
 *   <input type="hidden" name="select" value="">
 * </div>
 *
 * // File upload tile:
 * <div class="rsl-file-tile">
 *   <label class="rsl-file-label" tabindex="0">Upload File</label>
 *   <input type="file" class="rsl-file-input">
 *   <span class="rsl-file-filename"></span>
 * </div>
 *
 * // Data attribute theming:
 * <div class="rsl-slider" data-slider-track="#e0e0e0" data-slider-fill="#007bff">
 *   ...
 * </div>
 *
 * Public API:
 * All components are automatically initialized on DOMContentLoaded.
 * No manual JavaScript API is required - components work through HTML structure.
 */

(function() {
    'use strict';

    /**
     * Initialize all form elements on DOM ready
     */
    document.addEventListener('DOMContentLoaded', init);

    /**
     * Main initialization function
     * Sets up all form components: theming, sliders, file uploads, and selects
     */
    function init() {
        initDataAttributeTheming();
        initSliders();
        initFileUploadTiles();
        initCustomSelects();
    }

    /**
     * Map of data attribute names to CSS custom property names
     * @const
     * @type {Object<string, string>}
     */
    const DATA_VAR_MAP = {
        fieldBg: '--rsl-field-bg',
        fieldBorder: '--rsl-field-border',
        fieldRadius: '--rsl-field-radius',
        fieldText: '--rsl-field-text',
        fieldMuted: '--rsl-field-muted',
        fieldFocus: '--rsl-field-focus',
        fieldError: '--rsl-field-error',
        fieldSuccess: '--rsl-field-success',
        chipBg: '--rsl-chip-bg',
        chipBorder: '--rsl-chip-border',
        choiceBg: '--rsl-choice-bg',
        selectBg: '--rsl-select-bg',
        toggleOff: '--rsl-toggle-off',
        toggleOn: '--rsl-toggle-on',
        sliderTrack: '--rsl-slider-track',
        sliderFill: '--rsl-slider-fill',
        fileBg: '--rsl-file-bg'
    };

    /**
     * Convert camelCase string to kebab-case
     *
     * @param {string} camel - CamelCase string
     * @returns {string} Kebab-case string
     *
     * @example
     * toKebab('fieldBg') // returns 'field-bg'
     * toKebab('sliderTrack') // returns 'slider-track'
     */
    function toKebab(camel) {
        return camel.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
    }

    /**
     * Initialize data attribute theming system
     *
     * Scans the DOM for elements with theming data attributes and applies
     * corresponding CSS custom properties. This allows per-component color
     * customization without modifying CSS files.
     *
     * Supported attributes: data-field-bg, data-field-border, data-field-radius,
     * data-field-text, data-field-muted, data-field-focus, data-field-error,
     * data-field-success, data-chip-bg, data-chip-border, data-choice-bg,
     * data-select-bg, data-toggle-off, data-toggle-on, data-slider-track,
     * data-slider-fill, data-file-bg
     *
     * @example
     * <div class="rsl-slider" data-slider-fill="#ff0000">
     *   // Will set --rsl-slider-fill: #ff0000 on this element
     * </div>
     */
    function initDataAttributeTheming() {
        const dataAttrSelector = Object.keys(DATA_VAR_MAP)
            .map(key => `[data-${toKebab(key)}]`)
            .join(',');

        if (!dataAttrSelector) return;

        document.querySelectorAll(dataAttrSelector).forEach(element => {
            Object.entries(DATA_VAR_MAP).forEach(([dataKey, cssVar]) => {
                const attrName = `data-${toKebab(dataKey)}`;
                if (element.hasAttribute(attrName)) {
                    const value = element.getAttribute(attrName);
                    if (value && value.trim() !== '') {
                        element.style.setProperty(cssVar, value.trim());
                    }
                }
            });
        });
    }

    /**
     * Initialize slider value synchronization
     *
     * Finds all slider inputs and connects them to their value display elements.
     * Updates the display in real-time as the slider moves, showing the current
     * value with a percentage sign.
     *
     * @example
     * <div class="rsl-slider">
     *   <input type="range" class="rsl-slider-input" value="50">
     *   <span class="rsl-slider-value">50%</span>
     * </div>
     */
    function initSliders() {
        const sliders = document.querySelectorAll('.rsl-slider-input');

        sliders.forEach(slider => {
            const wrapper = slider.closest('.rsl-slider');
            if (!wrapper) return;

            const valueEl = wrapper.querySelector('.rsl-slider-value');
            if (!valueEl) return;

            /**
             * Update the value display element with current slider value
             */
            const updateValue = () => {
                valueEl.textContent = `${slider.value}%`;
            };

            slider.addEventListener('input', updateValue);
            updateValue(); // Set initial value
        });
    }

    /**
     * Initialize file upload tiles
     *
     * Sets up file input functionality with:
     * - Keyboard accessibility (Enter/Space to open file dialog)
     * - Filename display after selection
     * - Visual feedback on file selection
     * - Proper ARIA attributes and tabindex
     *
     * @example
     * <div class="rsl-file-tile">
     *   <label class="rsl-file-label">Choose File</label>
     *   <input type="file" class="rsl-file-input">
     *   <span class="rsl-file-filename"></span>
     * </div>
     */
    function initFileUploadTiles() {
        const fileTiles = document.querySelectorAll('.rsl-file-tile');

        fileTiles.forEach(tile => {
            const input = tile.querySelector('.rsl-file-input');
            const label = tile.querySelector('.rsl-file-label');
            const filenameEl = tile.querySelector('.rsl-file-filename');

            if (!input || !label || !filenameEl) return;

            // Make label keyboard accessible
            label.setAttribute('tabindex', '0');

            /**
             * Handle keyboard interaction for file upload label
             * @param {KeyboardEvent} evt - Keyboard event
             */
            label.addEventListener('keydown', (evt) => {
                if (evt.key === 'Enter' || evt.key === ' ') {
                    evt.preventDefault();
                    input.click();
                }
            });

            /**
             * Display selected filename
             */
            input.addEventListener('change', () => {
                if (input.files && input.files.length > 0) {
                    filenameEl.textContent = input.files[0].name;
                } else {
                    filenameEl.textContent = '';
                }
            });
        });
    }

    /**
     * Initialize custom select dropdowns
     *
     * Creates fully accessible custom select controls with:
     * - Click to toggle dropdown
     * - Keyboard navigation (Arrow keys to open/navigate, Enter/Space to select, Escape to close)
     * - ARIA attributes for screen readers
     * - Hidden input for form submission
     * - Click-outside-to-close behavior
     * - Focus management
     *
     * @example
     * <div class="rsl-select" data-open="false">
     *   <button class="rsl-select-toggle" aria-haspopup="listbox" aria-expanded="false">
     *     <span class="rsl-select-value">Select...</span>
     *   </button>
     *   <ul class="rsl-select-list" role="listbox" hidden>
     *     <li class="rsl-select-option" role="option" data-value="1">Option 1</li>
     *     <li class="rsl-select-option" role="option" data-value="2">Option 2</li>
     *   </ul>
     *   <input type="hidden" name="myselect" value="">
     * </div>
     */
    function initCustomSelects() {
        const selects = document.querySelectorAll('.rsl-select');

        selects.forEach(selectRoot => {
            const toggle = selectRoot.querySelector('.rsl-select-toggle');
            const list = selectRoot.querySelector('.rsl-select-list');
            const options = selectRoot.querySelectorAll('.rsl-select-option');
            const hiddenInput = selectRoot.querySelector('input[type="hidden"]');
            const valueSpan = selectRoot.querySelector('.rsl-select-value');

            if (!toggle || !list || !options.length || !hiddenInput || !valueSpan) return;

            /**
             * Close the select dropdown
             * Updates data attributes, ARIA states, and visibility
             */
            const close = () => {
                selectRoot.dataset.open = 'false';
                list.hidden = true;
                toggle.setAttribute('aria-expanded', 'false');
            };

            /**
             * Open the select dropdown
             * Updates data attributes, ARIA states, and visibility
             */
            const open = () => {
                selectRoot.dataset.open = 'true';
                list.hidden = false;
                toggle.setAttribute('aria-expanded', 'true');
            };

            /**
             * Toggle dropdown open/closed state
             */
            const toggleOpen = () => {
                if (selectRoot.dataset.open === 'true') {
                    close();
                } else {
                    open();
                }
            };

            // Toggle on click
            toggle.addEventListener('click', toggleOpen);

            /**
             * Handle keyboard interaction on toggle button
             * @param {KeyboardEvent} evt - Keyboard event
             */
            toggle.addEventListener('keydown', (evt) => {
                if (evt.key === 'ArrowDown' || evt.key === 'ArrowUp') {
                    evt.preventDefault();
                    open();
                    const first = list.querySelector('.rsl-select-option');
                    if (first) first.focus();
                } else if (evt.key === 'Escape') {
                    close();
                }
            });

            // Set up each option
            options.forEach(opt => {
                opt.setAttribute('tabindex', '-1');

                /**
                 * Select an option
                 * Updates hidden input value, display text, ARIA states, closes dropdown
                 */
                const choose = () => {
                    const value = opt.dataset.value || '';
                    hiddenInput.value = value;
                    valueSpan.textContent = opt.textContent.trim();

                    options.forEach(o => o.setAttribute('aria-selected', 'false'));
                    opt.setAttribute('aria-selected', 'true');

                    close();
                    toggle.focus();
                };

                // Select on click
                opt.addEventListener('click', choose);

                /**
                 * Handle keyboard interaction on options
                 * @param {KeyboardEvent} evt - Keyboard event
                 */
                opt.addEventListener('keydown', (evt) => {
                    if (evt.key === 'Enter' || evt.key === ' ') {
                        evt.preventDefault();
                        choose();
                    } else if (evt.key === 'Escape') {
                        evt.preventDefault();
                        close();
                        toggle.focus();
                    } else if (evt.key === 'ArrowDown') {
                        evt.preventDefault();
                        const next = opt.nextElementSibling;
                        if (next && next.classList.contains('rsl-select-option')) {
                            next.focus();
                        }
                    } else if (evt.key === 'ArrowUp') {
                        evt.preventDefault();
                        const prev = opt.previousElementSibling;
                        if (prev && prev.classList.contains('rsl-select-option')) {
                            prev.focus();
                        }
                    }
                });
            });

            /**
             * Close dropdown when clicking outside
             * @param {MouseEvent} evt - Click event
             */
            document.addEventListener('click', (evt) => {
                if (!selectRoot.contains(evt.target)) {
                    close();
                }
            });
        });
    }

})();
