/* ============================================
   RSL Progress Bar Component
   Version: 1.0.0
   Description: Powerful, flexible progress bars with
   multiple shapes, animations, thresholds, milestones,
   and full accessibility support.
   ============================================ */

(function() {
    'use strict';

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

    // Track initialized instances
    var instances = new Set();

    /**
     * Progress Bar Component
     * Full-featured progress indicators with extensive customization
     */
    window.RSL.Progress = {

        /**
         * Initialize all progress bars on the page
         */
        init: function() {
            var progressBars = document.querySelectorAll('[data-rsl-progress]');
            progressBars.forEach(function(el) {
                if (!instances.has(el)) {
                    RSL.Progress.create(el);
                    instances.add(el);
                }
            });
        },

        /**
         * Create/initialize a single progress bar
         * @param {HTMLElement} element - The progress bar container
         * @param {Object} options - Optional configuration override
         */
        create: function(element, options) {
            if (!element) return null;

            // Parse configuration from data attributes
            var config = parseConfig(element, options);

            // Store config on element
            element._rslProgress = config;

            // Build the progress bar based on shape
            switch (config.shape) {
                case 'circular':
                    buildCircular(element, config);
                    break;
                case 'gauge':
                case 'semi-circular':
                    buildGauge(element, config);
                    break;
                case 'vertical':
                    buildVertical(element, config);
                    break;
                case 'steps':
                    buildSteps(element, config);
                    break;
                default:
                    buildHorizontal(element, config);
            }

            // Set initial value
            RSL.Progress.setValue(element, config.value, false);

            // Handle buffer
            if (config.buffer !== null) {
                RSL.Progress.setBuffer(element, config.buffer);
            }

            // Add milestones
            if (config.milestones && config.milestones.length > 0) {
                addMilestones(element, config);
            }

            // Set up animate on view
            if (config.animateOnView) {
                setupAnimateOnView(element, config);
            }

            // Setup ARIA attributes
            setupAccessibility(element, config);

            // Track instance
            instances.add(element);

            return element;
        },

        /**
         * Set progress value
         * @param {HTMLElement} element - Progress bar element
         * @param {number} value - New value
         * @param {boolean} animate - Whether to animate (default true)
         */
        setValue: function(element, value, animate) {
            if (!element || !element._rslProgress) return;

            var config = element._rslProgress;
            var min = config.min;
            var max = config.max;
            animate = animate !== false;

            // Clamp value
            value = Math.max(min, Math.min(max, parseFloat(value) || 0));
            config.value = value;

            // Calculate percentage
            var percent = ((value - min) / (max - min)) * 100;

            // Update based on shape
            switch (config.shape) {
                case 'circular':
                    updateCircular(element, percent, animate);
                    break;
                case 'gauge':
                case 'semi-circular':
                    updateGauge(element, percent, animate);
                    break;
                case 'vertical':
                    updateVertical(element, percent, animate);
                    break;
                case 'steps':
                    updateSteps(element, value, config);
                    break;
                default:
                    updateHorizontal(element, percent, animate);
            }

            // Update label
            updateLabel(element, config);

            // Check thresholds
            if (config.thresholds) {
                updateThreshold(element, percent, config.thresholds);
            }

            // Update milestones
            if (config.milestones) {
                updateMilestones(element, percent);
            }

            // Update ARIA
            element.setAttribute('aria-valuenow', value);

            // Dispatch event
            element.dispatchEvent(new CustomEvent('rsl-progress-change', {
                bubbles: true,
                detail: { value: value, percent: percent, max: max, min: min }
            }));
        },

        /**
         * Get current value
         * @param {HTMLElement} element - Progress bar element
         * @returns {number} Current value
         */
        getValue: function(element) {
            if (!element || !element._rslProgress) return 0;
            return element._rslProgress.value;
        },

        /**
         * Set buffer value (for streaming/loading indicators)
         * @param {HTMLElement} element - Progress bar element
         * @param {number} value - Buffer value
         */
        setBuffer: function(element, value) {
            if (!element || !element._rslProgress) return;

            var config = element._rslProgress;
            var percent = ((value - config.min) / (config.max - config.min)) * 100;
            percent = Math.max(0, Math.min(100, percent));

            var buffer = element.querySelector('.rsl-progress-buffer');
            if (buffer) {
                buffer.style.width = percent + '%';
            }

            config.buffer = value;
        },

        /**
         * Set indeterminate state
         * @param {HTMLElement} element - Progress bar element
         * @param {boolean} indeterminate - Whether indeterminate
         */
        setIndeterminate: function(element, indeterminate) {
            if (!element) return;

            if (indeterminate) {
                element.classList.add('rsl-progress-indeterminate');
                element.removeAttribute('aria-valuenow');
            } else {
                element.classList.remove('rsl-progress-indeterminate');
                if (element._rslProgress) {
                    element.setAttribute('aria-valuenow', element._rslProgress.value);
                }
            }
        },

        /**
         * Animate value from current to target
         * @param {HTMLElement} element - Progress bar element
         * @param {number} to - Target value
         * @param {number} duration - Animation duration in ms
         * @param {Function} callback - Callback when complete
         */
        animate: function(element, to, duration, callback) {
            if (!element || !element._rslProgress) return;

            var config = element._rslProgress;
            var from = config.value;
            duration = duration || config.duration || 1000;

            var startTime = null;

            function step(timestamp) {
                if (!startTime) startTime = timestamp;
                var elapsed = timestamp - startTime;
                var progress = Math.min(elapsed / duration, 1);

                // Easing function (ease-out)
                var eased = 1 - Math.pow(1 - progress, 3);

                var currentValue = from + (to - from) * eased;
                RSL.Progress.setValue(element, currentValue, false);

                if (progress < 1) {
                    requestAnimationFrame(step);
                } else {
                    RSL.Progress.setValue(element, to, false);
                    if (typeof callback === 'function') {
                        callback();
                    }
                }
            }

            requestAnimationFrame(step);
        },

        /**
         * Increment value
         * @param {HTMLElement} element - Progress bar element
         * @param {number} amount - Amount to increment (default 1)
         */
        increment: function(element, amount) {
            if (!element || !element._rslProgress) return;
            amount = amount || 1;
            RSL.Progress.setValue(element, element._rslProgress.value + amount);
        },

        /**
         * Decrement value
         * @param {HTMLElement} element - Progress bar element
         * @param {number} amount - Amount to decrement (default 1)
         */
        decrement: function(element, amount) {
            if (!element || !element._rslProgress) return;
            amount = amount || 1;
            RSL.Progress.setValue(element, element._rslProgress.value - amount);
        },

        /**
         * Set segments for stacked progress
         * @param {HTMLElement} element - Progress bar element
         * @param {Array} segments - Array of {value, color, label} objects
         */
        setSegments: function(element, segments) {
            if (!element || !element._rslProgress) return;

            var config = element._rslProgress;
            config.segments = segments;

            buildSegments(element, config);
        },

        /**
         * Update thresholds configuration
         * @param {HTMLElement} element - Progress bar element
         * @param {Object} thresholds - Threshold configuration
         */
        setThresholds: function(element, thresholds) {
            if (!element || !element._rslProgress) return;

            element._rslProgress.thresholds = thresholds;

            // Recalculate current threshold
            var percent = RSL.Progress.getValue(element);
            updateThreshold(element, percent, thresholds);
        },

        /**
         * Reset progress to min value
         * @param {HTMLElement} element - Progress bar element
         */
        reset: function(element) {
            if (!element || !element._rslProgress) return;
            RSL.Progress.setValue(element, element._rslProgress.min);
        },

        /**
         * Complete progress (set to max)
         * @param {HTMLElement} element - Progress bar element
         */
        complete: function(element) {
            if (!element || !element._rslProgress) return;
            RSL.Progress.setValue(element, element._rslProgress.max);
        }
    };

    /**
     * Parse configuration from data attributes
     * @private
     */
    function parseConfig(element, options) {
        options = options || {};

        // Parse thresholds JSON
        var thresholds = null;
        var thresholdsAttr = element.getAttribute('data-thresholds');
        if (thresholdsAttr) {
            try {
                thresholds = JSON.parse(thresholdsAttr);
            } catch (e) {
                console.warn('RSL Progress: Invalid thresholds JSON');
            }
        }

        // Parse milestones JSON
        var milestones = null;
        var milestonesAttr = element.getAttribute('data-milestones');
        if (milestonesAttr) {
            try {
                milestones = JSON.parse(milestonesAttr);
            } catch (e) {
                console.warn('RSL Progress: Invalid milestones JSON');
            }
        }

        // Parse segments JSON
        var segments = null;
        var segmentsAttr = element.getAttribute('data-segments');
        if (segmentsAttr) {
            try {
                segments = JSON.parse(segmentsAttr);
            } catch (e) {
                console.warn('RSL Progress: Invalid segments JSON');
            }
        }

        return {
            value: parseFloat(element.getAttribute('data-value')) || options.value || 0,
            min: parseFloat(element.getAttribute('data-min')) || options.min || 0,
            max: parseFloat(element.getAttribute('data-max')) || options.max || 100,
            buffer: element.hasAttribute('data-buffer') ? parseFloat(element.getAttribute('data-buffer')) : null,
            label: element.getAttribute('data-label') || options.label || 'inside',
            labelFormat: element.getAttribute('data-label-format') || options.labelFormat || '{percent}%',
            variant: element.getAttribute('data-variant') || options.variant || 'primary',
            size: element.getAttribute('data-size') || options.size || 'md',
            shape: element.getAttribute('data-shape') || options.shape || 'horizontal',
            striped: element.hasAttribute('data-striped'),
            animated: element.hasAttribute('data-animated'),
            indeterminate: element.hasAttribute('data-indeterminate'),
            thresholds: thresholds || options.thresholds,
            milestones: milestones || options.milestones,
            segments: segments || options.segments,
            animateOnView: element.hasAttribute('data-animate-on-view'),
            duration: parseInt(element.getAttribute('data-duration'), 10) || options.duration || 1000,
            steps: parseInt(element.getAttribute('data-steps'), 10) || options.steps || 0,
            showValue: element.hasAttribute('data-show-value'),
            glow: element.hasAttribute('data-glow'),
            pulse: element.hasAttribute('data-pulse')
        };
    }

    /**
     * Build horizontal progress bar
     * @private
     */
    function buildHorizontal(element, config) {
        // Add base classes
        element.classList.add('rsl-progress');

        // Add variant class
        if (config.variant) {
            element.classList.add('rsl-progress-' + config.variant);
        }

        // Add size class
        if (config.size && config.size !== 'md') {
            element.classList.add('rsl-progress-' + config.size);
        }

        // Add striped
        if (config.striped) {
            element.classList.add('rsl-progress-striped');
        }

        // Add animated
        if (config.animated) {
            element.classList.add('rsl-progress-animated');
        }

        // Add glow
        if (config.glow) {
            element.classList.add('rsl-progress-glow');
        }

        // Add pulse
        if (config.pulse) {
            element.classList.add('rsl-progress-pulse');
        }

        // Add indeterminate
        if (config.indeterminate) {
            element.classList.add('rsl-progress-indeterminate');
        }

        // Handle label position
        if (config.label === 'outside') {
            element.classList.add('rsl-progress-label-outside');
            element.innerHTML = '<div class="rsl-progress-track"></div><span class="rsl-progress-label"></span>';
            var track = element.querySelector('.rsl-progress-track');

            // Add buffer if needed
            if (config.buffer !== null) {
                track.innerHTML = '<div class="rsl-progress-buffer"></div>';
            }

            track.innerHTML += '<div class="rsl-progress-bar"></div>';
        } else if (config.label === 'floating') {
            element.classList.add('rsl-progress-label-floating');

            // Add buffer if needed
            if (config.buffer !== null) {
                element.innerHTML = '<div class="rsl-progress-buffer"></div>';
            }

            element.innerHTML += '<div class="rsl-progress-bar"><span class="rsl-progress-label"></span></div>';
        } else if (config.label === 'hidden') {
            element.classList.add('rsl-progress-label-hidden');

            // Add buffer if needed
            if (config.buffer !== null) {
                element.innerHTML = '<div class="rsl-progress-buffer"></div>';
            }

            element.innerHTML += '<div class="rsl-progress-bar"><span class="rsl-progress-label"></span></div>';
        } else {
            // Inside (default)
            element.classList.add('rsl-progress-label-inside');

            // Add buffer if needed
            if (config.buffer !== null) {
                element.innerHTML = '<div class="rsl-progress-buffer"></div>';
            }

            element.innerHTML += '<div class="rsl-progress-bar"></div>';
        }

        // Handle segments
        if (config.segments && config.segments.length > 0) {
            element.classList.add('rsl-progress-stacked');
            buildSegments(element, config);
        }
    }

    /**
     * Build segments for stacked progress
     * @private
     */
    function buildSegments(element, config) {
        element.innerHTML = '';
        var total = config.segments.reduce(function(sum, seg) { return sum + seg.value; }, 0);

        config.segments.forEach(function(segment) {
            var segEl = document.createElement('div');
            segEl.className = 'rsl-progress-segment';
            segEl.style.width = (segment.value / config.max * 100) + '%';

            if (segment.color) {
                if (segment.color.startsWith('#') || segment.color.startsWith('rgb')) {
                    segEl.style.backgroundColor = segment.color;
                } else {
                    segEl.style.backgroundColor = 'var(--rsl-progress-' + segment.color + ', ' + segment.color + ')';
                }
            }

            if (segment.label) {
                segEl.textContent = segment.label;
            }

            element.appendChild(segEl);
        });
    }

    /**
     * Build circular progress
     * @private
     */
    function buildCircular(element, config) {
        element.classList.add('rsl-progress', 'rsl-progress-circular');

        if (config.size && config.size !== 'md') {
            element.classList.add('rsl-progress-' + config.size);
        }

        if (config.variant) {
            element.classList.add('rsl-progress-' + config.variant);
        }

        // SVG circle
        var size = parseInt(getComputedStyle(element).getPropertyValue('--rsl-progress-size'), 10) || 120;
        var stroke = parseInt(getComputedStyle(element).getPropertyValue('--rsl-progress-stroke'), 10) || 8;
        var radius = (size - stroke) / 2;
        var circumference = radius * 2 * Math.PI;

        element.innerHTML = '\
            <svg viewBox="0 0 ' + size + ' ' + size + '">\
                <circle class="progress-track" cx="' + (size / 2) + '" cy="' + (size / 2) + '" r="' + radius + '"></circle>\
                <circle class="progress-fill" cx="' + (size / 2) + '" cy="' + (size / 2) + '" r="' + radius + '" \
                    stroke-dasharray="' + circumference + '" stroke-dashoffset="' + circumference + '"></circle>\
            </svg>\
            <span class="rsl-progress-label"></span>';

        // Store circumference for updates
        element._circumference = circumference;
    }

    /**
     * Build gauge/semi-circular progress
     * @private
     */
    function buildGauge(element, config) {
        element.classList.add('rsl-progress', 'rsl-progress-gauge');

        if (config.size && config.size !== 'md') {
            element.classList.add('rsl-progress-' + config.size);
        }

        if (config.variant) {
            element.classList.add('rsl-progress-' + config.variant);
        }

        var size = parseInt(getComputedStyle(element).getPropertyValue('--rsl-progress-size'), 10) || 200;
        var stroke = parseInt(getComputedStyle(element).getPropertyValue('--rsl-progress-stroke'), 10) || 12;
        var radius = (size - stroke) / 2;
        var circumference = radius * Math.PI; // Half circle

        element.innerHTML = '\
            <svg viewBox="0 0 ' + size + ' ' + (size / 2 + stroke) + '">\
                <path class="progress-track" \
                    d="M ' + (stroke / 2) + ',' + (size / 2) + ' A ' + radius + ',' + radius + ' 0 0 1 ' + (size - stroke / 2) + ',' + (size / 2) + '" \
                    fill="none"></path>\
                <path class="progress-fill" \
                    d="M ' + (stroke / 2) + ',' + (size / 2) + ' A ' + radius + ',' + radius + ' 0 0 1 ' + (size - stroke / 2) + ',' + (size / 2) + '" \
                    fill="none" stroke-dasharray="' + circumference + '" stroke-dashoffset="' + circumference + '"></path>\
            </svg>\
            <span class="rsl-progress-label"></span>';

        element._circumference = circumference;
    }

    /**
     * Build vertical progress
     * @private
     */
    function buildVertical(element, config) {
        element.classList.add('rsl-progress', 'rsl-progress-vertical');

        if (config.size && config.size !== 'md') {
            element.classList.add('rsl-progress-' + config.size);
        }

        if (config.variant) {
            element.classList.add('rsl-progress-' + config.variant);
        }

        if (config.striped) {
            element.classList.add('rsl-progress-striped');
        }

        element.innerHTML = '<div class="rsl-progress-bar"></div>';
    }

    /**
     * Build step progress
     * @private
     */
    function buildSteps(element, config) {
        element.classList.add('rsl-progress', 'rsl-progress-steps');

        if (config.variant) {
            element.classList.add('rsl-progress-' + config.variant);
        }

        var steps = config.steps || config.max;
        element.innerHTML = '';

        for (var i = 1; i <= steps; i++) {
            var step = document.createElement('div');
            step.className = 'rsl-progress-step';
            step.setAttribute('data-step', i);

            // Add marker if showing value
            if (config.showValue) {
                var marker = document.createElement('span');
                marker.className = 'rsl-progress-step-marker';
                marker.textContent = i;
                step.appendChild(marker);
            }

            element.appendChild(step);
        }
    }

    /**
     * Update horizontal progress
     * @private
     */
    function updateHorizontal(element, percent, animate) {
        var bar = element.querySelector('.rsl-progress-bar');
        if (bar) {
            if (!animate) {
                bar.style.transition = 'none';
            }
            bar.style.width = percent + '%';
            if (!animate) {
                // Force reflow
                bar.offsetHeight;
                bar.style.transition = '';
            }
        }

        // Update floating label position
        var floatingLabel = element.querySelector('.rsl-progress-label-floating .rsl-progress-label');
        if (floatingLabel) {
            floatingLabel.style.left = percent + '%';
        }
    }

    /**
     * Update circular progress
     * @private
     */
    function updateCircular(element, percent, animate) {
        var fill = element.querySelector('.progress-fill');
        if (fill && element._circumference) {
            var offset = element._circumference - (percent / 100) * element._circumference;
            fill.style.strokeDashoffset = offset;
        }
    }

    /**
     * Update gauge progress
     * @private
     */
    function updateGauge(element, percent, animate) {
        var fill = element.querySelector('.progress-fill');
        if (fill && element._circumference) {
            var offset = element._circumference - (percent / 100) * element._circumference;
            fill.style.strokeDashoffset = offset;
        }
    }

    /**
     * Update vertical progress
     * @private
     */
    function updateVertical(element, percent, animate) {
        var bar = element.querySelector('.rsl-progress-bar');
        if (bar) {
            if (!animate) {
                bar.style.transition = 'none';
            }
            bar.style.height = percent + '%';
            if (!animate) {
                bar.offsetHeight;
                bar.style.transition = '';
            }
        }
    }

    /**
     * Update step progress
     * @private
     */
    function updateSteps(element, value, config) {
        var steps = element.querySelectorAll('.rsl-progress-step');
        steps.forEach(function(step, index) {
            var stepNum = index + 1;
            step.classList.remove('completed', 'active');

            if (stepNum < value) {
                step.classList.add('completed');
            } else if (stepNum === Math.ceil(value)) {
                step.classList.add('active');
            }
        });
    }

    /**
     * Update label
     * @private
     */
    function updateLabel(element, config) {
        var label = element.querySelector('.rsl-progress-label');
        if (!label && config.label === 'inside') {
            var bar = element.querySelector('.rsl-progress-bar');
            if (bar) {
                label = document.createElement('span');
                label.className = 'rsl-progress-label';
                bar.appendChild(label);
            }
        }

        if (label) {
            var percent = ((config.value - config.min) / (config.max - config.min)) * 100;
            var text = config.labelFormat
                .replace('{value}', Math.round(config.value))
                .replace('{percent}', Math.round(percent))
                .replace('{max}', config.max)
                .replace('{min}', config.min);

            label.textContent = text;
        }
    }

    /**
     * Update threshold state
     * @private
     */
    function updateThreshold(element, percent, thresholds) {
        // Reset
        element.removeAttribute('data-threshold-state');

        // Thresholds format: { warning: 50, danger: 80 } or { success: 30, warning: 60, danger: 80 }
        var state = 'success';

        if (thresholds.success !== undefined && percent >= thresholds.success) {
            state = 'success';
        }
        if (thresholds.warning !== undefined && percent >= thresholds.warning) {
            state = 'warning';
        }
        if (thresholds.danger !== undefined && percent >= thresholds.danger) {
            state = 'danger';
        }

        element.setAttribute('data-threshold-state', state);
    }

    /**
     * Add milestones to progress bar
     * @private
     */
    function addMilestones(element, config) {
        var container = document.createElement('div');
        container.className = 'rsl-progress-milestones';

        config.milestones.forEach(function(milestone) {
            var percent = ((milestone.value - config.min) / (config.max - config.min)) * 100;

            var marker = document.createElement('div');
            marker.className = 'rsl-progress-milestone';
            marker.style.left = percent + '%';
            marker.setAttribute('data-milestone-value', milestone.value);

            if (milestone.label) {
                var label = document.createElement('span');
                label.className = 'rsl-progress-milestone-label';
                label.textContent = milestone.label;
                marker.appendChild(label);
            }

            container.appendChild(marker);
        });

        element.appendChild(container);
    }

    /**
     * Update milestone states
     * @private
     */
    function updateMilestones(element, percent) {
        var milestones = element.querySelectorAll('.rsl-progress-milestone');
        milestones.forEach(function(milestone) {
            var value = parseFloat(milestone.getAttribute('data-milestone-value'));
            var config = element._rslProgress;
            var milestonePercent = ((value - config.min) / (config.max - config.min)) * 100;

            if (percent >= milestonePercent) {
                milestone.classList.add('completed');
            } else {
                milestone.classList.remove('completed');
            }
        });
    }

    /**
     * Setup animate on view (Intersection Observer)
     * @private
     */
    function setupAnimateOnView(element, config) {
        // Store original value and set to min
        var targetValue = config.value;
        config.value = config.min;

        // Initial state at min
        RSL.Progress.setValue(element, config.min, false);

        // Create observer
        var observer = new IntersectionObserver(function(entries) {
            entries.forEach(function(entry) {
                if (entry.isIntersecting) {
                    // Animate to target value
                    RSL.Progress.animate(element, targetValue, config.duration);
                    observer.unobserve(element);
                }
            });
        }, {
            threshold: 0.2
        });

        observer.observe(element);
    }

    /**
     * Setup accessibility attributes
     * @private
     */
    function setupAccessibility(element, config) {
        element.setAttribute('role', 'progressbar');
        element.setAttribute('aria-valuemin', config.min);
        element.setAttribute('aria-valuemax', config.max);

        if (!config.indeterminate) {
            element.setAttribute('aria-valuenow', config.value);
        }

        // Add label if not present
        if (!element.getAttribute('aria-label')) {
            element.setAttribute('aria-label', 'Progress');
        }
    }

    /**
     * Auto-initialize on DOMContentLoaded
     */
    document.addEventListener('DOMContentLoaded', function() {
        RSL.Progress.init();
    });

    /**
     * Re-initialize for dynamically added content
     */
    if (typeof MutationObserver !== 'undefined') {
        var observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1) {
                        if (node.hasAttribute && node.hasAttribute('data-rsl-progress')) {
                            RSL.Progress.create(node);
                        }
                        var nested = node.querySelectorAll && node.querySelectorAll('[data-rsl-progress]');
                        if (nested) {
                            nested.forEach(function(el) {
                                if (!instances.has(el)) {
                                    RSL.Progress.create(el);
                                }
                            });
                        }
                    }
                });
            });
        });

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

})();
