/**
 * RSL Color Adjustment Utilities
 *
 * Comprehensive color manipulation toolkit for dynamic theming and accessibility.
 * Provides functions to detect color luminance, lighten/darken colors, adjust text
 * contrast, and apply alternating color schemes to UI components. Supports both
 * HEX and RGB color formats with automatic conversion.
 *
 * @fileoverview Color utilities for accessibility, theming, and dynamic styling
 * @version 2.0.0
 * @license MIT
 *
 * Key Features:
 * - Light/dark color detection using HSP algorithm
 * - Color lightening/darkening (fixed amount or percentage)
 * - Automatic text contrast adjustment for accessibility
 * - Alternating row colors for accordions and lists
 * - Alert message color theming
 * - WCAG-compliant color contrast ratios
 * - Support for HEX and RGB color formats
 *
 * Usage:
 * // Check if color is light or dark
 * const isDark = !isLight('#333333'); // true
 *
 * // Lighten a color
 * const lighter = adjustColor('#ff0000', 30); // Lighter red
 *
 * // Adjust by percentage
 * const tinted = adjustColorPercentage('#0000ff', 0.2); // 20% lighter blue
 *
 * // Auto-initialize on page load
 * // Colors adjust automatically based on background
 *
 * Public API:
 * - isLight(color) - Check if color is light
 * - adjustColor(color, amount) - Lighten/darken by fixed amount
 * - adjustColorPercentage(color, percentage) - Adjust by percentage
 * - applyAlternateColors() - Apply alternating row colors
 * - adjustTextColor() - Ensure text contrast for alerts
 * - adjustAlertMessageStaticColors() - Theme alert backgrounds
 */

(function() {
    'use strict';

    /**
     * Check if a color is light or dark using HSP color model
     *
     * Uses the HSP (Highly Sensitive Poo) equation to determine perceived
     * brightness of a color. More accurate than simple RGB averaging because
     * it accounts for human eye sensitivity to different wavelengths.
     *
     * @param {string} color - Color in HEX (#RRGGBB) or RGB (rgb(r,g,b)) format
     * @returns {boolean} True if color is light (HSP > 127.5), false if dark
     *
     * @example
     * isLight('#ffffff'); // true (white)
     * isLight('#000000'); // false (black)
     * isLight('rgb(128, 128, 128)'); // true (medium gray)
     */
    window.isLight = function(color) {
        let r, g, b;

        // Parse RGB format
        if (color.match(/^rgb/)) {
            const matches = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
            if (matches) {
                r = matches[1];
                g = matches[2];
                b = matches[3];
            }
        }
        // Parse HEX format
        else {
            const hex = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&'));
            r = hex >> 16;
            g = hex >> 8 & 255;
            b = hex & 255;
        }

        // HSP equation from http://alienryderflex.com/hsp.html
        const hsp = Math.sqrt(0.299 * (r * r) + 0.587 * (g * g) + 0.114 * (b * b));
        return hsp > 127.5;
    };

    /**
     * Lighten or darken a color by a fixed amount
     *
     * Adds or subtracts a fixed value from each RGB channel. Clamps values
     * between 0-255. Preserves color format (HEX stays HEX, RGB stays RGB).
     *
     * @param {string} color - Color in HEX or RGB format
     * @param {number} amount - Amount to adjust (-255 to +255). Positive lightens, negative darkens
     * @returns {string} Adjusted color in same format as input
     *
     * @example
     * adjustColor('#ff0000', 30);      // Lighter red: #ff1e1e
     * adjustColor('#ff0000', -30);     // Darker red: #e10000
     * adjustColor('rgb(100,100,100)', 50); // Lighter gray: rgb(150,150,150)
     */
    window.adjustColor = function(color, amount) {
        if (color.startsWith('#')) {
            // HEX color adjustment
            return '#' + color.replace(/^#/, '').replace(/../g, colorPart => {
                const adjusted = Math.min(255, Math.max(0, parseInt(colorPart, 16) + amount));
                return ('0' + adjusted.toString(16)).substr(-2);
            });
        } else {
            // RGB color adjustment
            const rgb = color.match(/(\d+),\s*(\d+),\s*(\d+)/);
            const r = Math.min(255, Math.max(0, parseInt(rgb[1]) + amount));
            const g = Math.min(255, Math.max(0, parseInt(rgb[2]) + amount));
            const b = Math.min(255, Math.max(0, parseInt(rgb[3]) + amount));
            return `rgb(${r}, ${g}, ${b})`;
        }
    };

    /**
     * Lighten or darken a color by a percentage
     *
     * More sophisticated than fixed adjustment - lightening adds percentage
     * of distance to white (255), darkening multiplies by (1 - percentage).
     * Produces more natural-looking color transitions.
     *
     * @param {string} color - Color in HEX or RGB format
     * @param {number} percentage - Percentage to adjust (-1.0 to +1.0)
     *   - Positive: lighten (0.2 = 20% lighter)
     *   - Negative: darken (-0.2 = 20% darker)
     * @returns {string} Adjusted color in same format as input
     *
     * @example
     * adjustColorPercentage('#ff0000', 0.2);   // 20% lighter red
     * adjustColorPercentage('#ff0000', -0.5);  // 50% darker red
     * adjustColorPercentage('rgb(200,100,50)', 0.3); // 30% lighter
     */
    window.adjustColorPercentage = function(color, percentage) {
        if (color.startsWith('#')) {
            // HEX color percentage adjustment
            let decimalColor = parseInt(color.slice(1), 16);
            let r = decimalColor >> 16;
            let g = (decimalColor >> 8) & 255;
            let b = decimalColor & 255;

            if (percentage < 0) {
                // Darken: multiply by (1 + percentage)
                r *= (1 + percentage);
                g *= (1 + percentage);
                b *= (1 + percentage);
            } else {
                // Lighten: add percentage of distance to white
                r += Math.round((255 - r) * percentage);
                g += Math.round((255 - g) * percentage);
                b += Math.round((255 - b) * percentage);
            }

            return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        } else {
            // RGB color percentage adjustment
            const rgb = color.match(/(\d+),\s*(\d+),\s*(\d+)/);
            let r = parseInt(rgb[1]);
            let g = parseInt(rgb[2]);
            let b = parseInt(rgb[3]);

            if (percentage < 0) {
                r *= (1 + percentage);
                g *= (1 + percentage);
                b *= (1 + percentage);
            } else {
                r += Math.round((255 - r) * percentage);
                g += Math.round((255 - g) * percentage);
                b += Math.round((255 - b) * percentage);
            }

            return `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`;
        }
    };

    /**
     * Apply alternating colors to accordion headers
     *
     * Creates visual distinction between adjacent items by alternating background
     * colors. Supports custom parent background colors and automatic light/dark
     * adjustment. Caches initial colors for performance on resize.
     *
     * Attributes:
     * - data-alternate="true" - Enable alternating colors
     * - data-custom-colors="true" - Use parent background color
     * - data-initial-colors - Internal cache of original colors
     *
     * @example
     * // HTML:
     * <div class="slot-layout classic-accordion" data-alternate="true">
     *   <div class="alternate-item">Item 1</div>
     *   <div class="alternate-item">Item 2</div>
     * </div>
     */
    window.applyAlternateColors = function() {
        const parents = document.querySelectorAll('.slot-layout.classic-accordion');

        parents.forEach(function(parent) {
            const children = parent.querySelectorAll('.alternate-item');
            const alternate = parent.getAttribute('data-alternate') === 'true';
            const customColors = parent.getAttribute('data-custom-colors') === 'true';

            let parentColor = customColors ? window.getComputedStyle(parent).backgroundColor : null;
            if (customColors && !parentColor) {
                console.error("Parent element does not have a background color.");
                return;
            }

            // Cache initial colors on first run
            let initialColors = parent.getAttribute('data-initial-colors');
            if (!initialColors) {
                initialColors = Array.from(children).map(child => window.getComputedStyle(child).backgroundColor);
                parent.setAttribute('data-initial-colors', JSON.stringify(initialColors));
            } else {
                initialColors = JSON.parse(initialColors);
            }

            // Remove preset color classes if custom colors not enabled
            if (!customColors) {
                ["rsl-bg-info", "rsl-bg-warning", "rsl-bg-danger", "rsl-bg-success", "rsl-bg-default"].forEach(cls => {
                    if (parent.classList.contains(cls)) {
                        parent.classList.remove(cls);
                    }
                });
            }

            // Apply alternating colors
            children.forEach(function(child, index) {
                let color;
                if (alternate) {
                    if (customColors) {
                        // Alternate between parent color and slightly adjusted version
                        color = index % 2 !== 0
                            ? adjustColor(parentColor, isLight(parentColor) ? -30 : 30)
                            : parentColor;
                    } else {
                        // Alternate using cached initial colors
                        color = initialColors[index];
                        color = index % 2 !== 0
                            ? adjustColor(color, isLight(color) ? -10 : 10)
                            : color;
                    }
                } else {
                    // No alternation - use parent color or cached color
                    color = customColors ? parentColor : initialColors[index];
                }
                child.style.backgroundColor = color;
            });
        });
    };

    /**
     * Adjust text color for accessible contrast in alerts
     *
     * Automatically determines appropriate text color based on alert background
     * color to ensure WCAG-compliant contrast ratios. Light backgrounds get dark
     * text, dark backgrounds get light text.
     *
     * @param {HTMLElement} [specificAlert] - Specific alert to adjust, or all if omitted
     *
     * @example
     * adjustTextColor(); // Adjust all alerts
     * adjustTextColor(document.querySelector('.inlay-alert')); // Adjust one
     */
    window.adjustTextColor = function(specificAlert) {
        const alerts = specificAlert ? [specificAlert] : document.querySelectorAll('.inlay-alert');

        alerts.forEach(function(alert) {
            const bgColor = window.getComputedStyle(alert).backgroundColor;

            let textColor, h4Color;
            if (isLight(bgColor)) {
                // Light background: dark text (80% darker)
                textColor = adjustColorPercentage(bgColor, -0.8);
                h4Color = adjustColorPercentage(bgColor, -0.9);
            } else {
                // Dark background: light text (80% lighter)
                textColor = adjustColorPercentage(bgColor, 0.8);
                h4Color = adjustColorPercentage(bgColor, 0.9);
            }

            alert.style.color = textColor;

            // Adjust heading color if present
            const h4Element = alert.querySelector('.alert-message h4');
            if (h4Element) {
                const titleColor = h4Element.style.color;
                h4Element.style.color = titleColor !== '' ? titleColor : '#fff';
            }
        });
    };

    /**
     * Apply subtle background color to alert message wrappers
     *
     * Creates visual depth by applying a slightly adjusted background color
     * to .alert-message-around elements based on their parent alert's color.
     *
     * @example
     * adjustAlertMessageStaticColors(); // Auto-called on page load
     */
    window.adjustAlertMessageStaticColors = function() {
        const elements = document.querySelectorAll('.alert-message-around');

        elements.forEach(function(element) {
            const parentElement = element.closest('.inlay-alert');
            if (!parentElement) return;

            let bgColor = window.getComputedStyle(parentElement).backgroundColor;

            // Adjust background slightly based on luminance
            if (!isLight(bgColor)) {
                bgColor = adjustColor(bgColor, -10);  // Darken slightly
            } else {
                bgColor = adjustColor(bgColor, 10);   // Lighten slightly
            }

            element.style.backgroundColor = bgColor;
        });
    };

    /**
     * Initialize all color adjustments on DOM ready
     */
    document.addEventListener('DOMContentLoaded', function() {
        applyAlternateColors();
        adjustTextColor();
        adjustAlertMessageStaticColors();

        // Initialize focus indicator if available
        if (typeof focusIndicator === 'function') {
            focusIndicator();
        }

        // Initialize text truncation if available
        if (typeof adjustTextOnResize === 'function') {
            adjustTextOnResize();
        }
    });

    /**
     * Recalculate colors on window resize
     * Ensures responsive layouts maintain proper color contrast
     */
    window.addEventListener('resize', adjustTextColor);
    window.addEventListener('resize', adjustAlertMessageStaticColors);
    window.addEventListener('resize', applyAlternateColors);

    if (typeof adjustTextOnResize === 'function') {
        window.addEventListener('resize', adjustTextOnResize);
    }

})();
