/**
 * Custom Color Picker Component
 * Consistent across all operating systems and browsers
 */

class ColorPicker {
    constructor(container, options = {}) {
        this.container = typeof container === 'string' ? document.querySelector(container) : container;
        this.options = {
            initialColor: options.initialColor || '#FF0000',
            onColorChange: options.onColorChange || null,
            showHexInput: options.showHexInput !== false,
            ...options
        };
        this.currentColor = this.options.initialColor;
        this.isOpen = false;
        this.init();
    }

    init() {
        this.createPicker();
        this.setupEventListeners();
        this.updateColor(this.options.initialColor);
    }

    createPicker() {
        this.container.innerHTML = '';
        this.container.className = 'color-picker-container';

        // Color preview button
        this.previewBtn = document.createElement('button');
        this.previewBtn.className = 'color-picker-preview';
        this.previewBtn.type = 'button';
        this.previewBtn.style.backgroundColor = this.currentColor;
        this.previewBtn.setAttribute('aria-label', 'Open color picker');

        // Dropdown panel
        this.panel = document.createElement('div');
        this.panel.className = 'color-picker-panel';
        this.panel.style.display = 'none';

        // Main color area (hue/saturation)
        this.mainArea = document.createElement('div');
        this.mainArea.className = 'color-picker-main';
        this.mainCanvas = document.createElement('canvas');
        this.mainCanvas.width = 200;
        this.mainCanvas.height = 200;
        this.mainCanvas.className = 'color-picker-canvas';
        this.mainArea.appendChild(this.mainCanvas);

        // Main area cursor
        this.mainCursor = document.createElement('div');
        this.mainCursor.className = 'color-picker-cursor';
        this.mainArea.appendChild(this.mainCursor);

        // Hue slider
        this.hueArea = document.createElement('div');
        this.hueArea.className = 'color-picker-hue';
        this.hueCanvas = document.createElement('canvas');
        this.hueCanvas.width = 20;
        this.hueCanvas.height = 200;
        this.hueCanvas.className = 'color-picker-canvas';
        this.hueArea.appendChild(this.hueCanvas);

        // Hue slider cursor
        this.hueCursor = document.createElement('div');
        this.hueCursor.className = 'color-picker-hue-cursor';
        this.hueArea.appendChild(this.hueCursor);

        // Controls section
        this.controls = document.createElement('div');
        this.controls.className = 'color-picker-controls';

        // Hex input
        if (this.options.showHexInput) {
            this.hexInput = document.createElement('input');
            this.hexInput.type = 'text';
            this.hexInput.className = 'color-picker-hex';
            this.hexInput.placeholder = '#000000';
            this.hexInput.maxLength = 7;
            this.controls.appendChild(this.hexInput);
        }

        // RGB inputs and sliders
        this.rgbContainer = document.createElement('div');
        this.rgbContainer.className = 'color-picker-rgb';
        
        ['R', 'G', 'B'].forEach((label, index) => {
            const wrapper = document.createElement('div');
            wrapper.className = 'color-picker-rgb-item';
            wrapper.dataset.channel = label.toLowerCase();
            
            const labelEl = document.createElement('label');
            labelEl.textContent = label;
            
            const slider = document.createElement('input');
            slider.type = 'range';
            slider.className = 'color-picker-rgb-slider';
            slider.min = 0;
            slider.max = 255;
            slider.value = 0;
            slider.dataset.channel = label.toLowerCase();
            
            const input = document.createElement('input');
            input.type = 'number';
            input.className = 'color-picker-rgb-input';
            input.min = 0;
            input.max = 255;
            input.value = 0;
            input.dataset.channel = label.toLowerCase();
            
            wrapper.appendChild(labelEl);
            wrapper.appendChild(slider);
            wrapper.appendChild(input);
            this.rgbContainer.appendChild(wrapper);
            
            this[`rgb${label}Slider`] = slider;
            this[`rgb${label}`] = input;
        });
        
        this.controls.appendChild(this.rgbContainer);

        // Assemble panel
        const pickerArea = document.createElement('div');
        pickerArea.className = 'color-picker-area';
        pickerArea.appendChild(this.mainArea);
        pickerArea.appendChild(this.hueArea);
        
        this.panel.appendChild(pickerArea);
        this.panel.appendChild(this.controls);

        // Assemble container
        this.container.appendChild(this.previewBtn);
        this.container.appendChild(this.panel);

        // Draw canvases
        this.drawHueCanvas();
        this.drawMainCanvas(1.0); // Start with full saturation
    }

    setupEventListeners() {
        // Toggle panel
        this.previewBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            this.toggle();
        });

        // Close on outside click
        document.addEventListener('click', (e) => {
            if (!this.container.contains(e.target) && this.isOpen) {
                this.close();
            }
        });

        // Main area interaction
        let isMainDragging = false;
        this.mainCanvas.addEventListener('mousedown', (e) => {
            isMainDragging = true;
            this.handleMainAreaClick(e);
        });
        this.mainCanvas.addEventListener('mousemove', (e) => {
            if (isMainDragging) {
                this.handleMainAreaClick(e);
            }
        });
        document.addEventListener('mouseup', () => {
            isMainDragging = false;
        });

        // Touch support for main area
        this.mainCanvas.addEventListener('touchstart', (e) => {
            e.preventDefault();
            isMainDragging = true;
            this.handleMainAreaClick(e.touches[0]);
        });
        this.mainCanvas.addEventListener('touchmove', (e) => {
            e.preventDefault();
            if (isMainDragging) {
                this.handleMainAreaClick(e.touches[0]);
            }
        });
        this.mainCanvas.addEventListener('touchend', () => {
            isMainDragging = false;
        });

        // Hue slider interaction
        let isHueDragging = false;
        this.hueCanvas.addEventListener('mousedown', (e) => {
            isHueDragging = true;
            this.handleHueClick(e);
        });
        this.hueCanvas.addEventListener('mousemove', (e) => {
            if (isHueDragging) {
                this.handleHueClick(e);
            }
        });
        document.addEventListener('mouseup', () => {
            isHueDragging = false;
        });

        // Touch support for hue slider
        this.hueCanvas.addEventListener('touchstart', (e) => {
            e.preventDefault();
            isHueDragging = true;
            this.handleHueClick(e.touches[0]);
        });
        this.hueCanvas.addEventListener('touchmove', (e) => {
            e.preventDefault();
            if (isHueDragging) {
                this.handleHueClick(e.touches[0]);
            }
        });
        this.hueCanvas.addEventListener('touchend', () => {
            isHueDragging = false;
        });

        // Hex input
        if (this.hexInput) {
            this.hexInput.addEventListener('input', (e) => {
                const value = e.target.value;
                if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
                    this.updateColor(value);
                }
            });
            this.hexInput.addEventListener('blur', (e) => {
                const value = e.target.value;
                if (!/^#[0-9A-Fa-f]{6}$/.test(value) && value.length > 0) {
                    e.target.value = this.currentColor;
                }
            });
        }

        // RGB inputs and sliders
        ['R', 'G', 'B'].forEach(label => {
            // Slider change
            this[`rgb${label}Slider`].addEventListener('input', (e) => {
                const value = parseInt(e.target.value) || 0;
                this[`rgb${label}`].value = value;
                const r = parseInt(this.rgbR.value) || 0;
                const g = parseInt(this.rgbG.value) || 0;
                const b = parseInt(this.rgbB.value) || 0;
                const hex = this.rgbToHex(r, g, b);
                this.updateColor(hex, false); // Don't update RGB inputs/sliders to avoid loop
            });
            
            // Input change
            this[`rgb${label}`].addEventListener('input', (e) => {
                let value = parseInt(e.target.value) || 0;
                value = Math.max(0, Math.min(255, value)); // Clamp to 0-255
                e.target.value = value;
                this[`rgb${label}Slider`].value = value;
                const r = parseInt(this.rgbR.value) || 0;
                const g = parseInt(this.rgbG.value) || 0;
                const b = parseInt(this.rgbB.value) || 0;
                const hex = this.rgbToHex(r, g, b);
                this.updateColor(hex, false); // Don't update RGB inputs/sliders to avoid loop
            });
        });
    }

    drawHueCanvas() {
        const ctx = this.hueCanvas.getContext('2d');
        const gradient = ctx.createLinearGradient(0, 0, 0, 200);
        
        for (let i = 0; i <= 6; i++) {
            const hue = i * 60;
            gradient.addColorStop(i / 6, `hsl(${hue}, 100%, 50%)`);
        }
        
        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, 20, 200);
    }

    drawMainCanvas(hue) {
        const ctx = this.mainCanvas.getContext('2d');
        
        // Saturation gradient (left to right)
        const satGradient = ctx.createLinearGradient(0, 0, 200, 0);
        satGradient.addColorStop(0, `hsl(${hue}, 0%, 50%)`);
        satGradient.addColorStop(1, `hsl(${hue}, 100%, 50%)`);
        ctx.fillStyle = satGradient;
        ctx.fillRect(0, 0, 200, 200);
        
        // Brightness gradient (top to bottom)
        const brightGradient = ctx.createLinearGradient(0, 0, 0, 200);
        brightGradient.addColorStop(0, 'rgba(255, 255, 255, 0)');
        brightGradient.addColorStop(1, 'rgba(0, 0, 0, 1)');
        ctx.fillStyle = brightGradient;
        ctx.fillRect(0, 0, 200, 200);
    }

    handleMainAreaClick(e) {
        const rect = this.mainCanvas.getBoundingClientRect();
        const x = Math.max(0, Math.min(200, e.clientX - rect.left));
        const y = Math.max(0, Math.min(200, e.clientY - rect.top));
        
        const saturation = x / 200;
        const brightness = 1 - (y / 200);
        
        this.updateColorFromHSB(this.hue, saturation, brightness);
        this.updateCursor(x, y);
    }

    handleHueClick(e) {
        const rect = this.hueCanvas.getBoundingClientRect();
        const y = Math.max(0, Math.min(200, e.clientY - rect.top));
        const hue = (y / 200) * 360;
        
        this.hue = hue;
        this.drawMainCanvas(hue);
        this.updateHueCursor(y);
        
        // Recalculate color with new hue
        const rect2 = this.mainCanvas.getBoundingClientRect();
        const x = parseFloat(this.mainCursor.style.left) || 0;
        const y2 = parseFloat(this.mainCursor.style.top) || 0;
        const saturation = x / 200;
        const brightness = 1 - (y2 / 200);
        this.updateColorFromHSB(hue, saturation, brightness);
    }

    updateColorFromHSB(h, s, v) {
        const rgb = this.hsbToRgb(h, s, v);
        const hex = this.rgbToHex(rgb.r, rgb.g, rgb.b);
        this.updateColor(hex);
    }

    hsbToRgb(h, s, v) {
        h = h / 360;
        const i = Math.floor(h * 6);
        const f = h * 6 - i;
        const p = v * (1 - s);
        const q = v * (1 - f * s);
        const t = v * (1 - (1 - f) * s);
        
        let r, g, b;
        switch (i % 6) {
            case 0: r = v; g = t; b = p; break;
            case 1: r = q; g = v; b = p; break;
            case 2: r = p; g = v; b = t; break;
            case 3: r = p; g = q; b = v; break;
            case 4: r = t; g = p; b = v; break;
            case 5: r = v; g = p; b = q; break;
        }
        
        return {
            r: Math.round(r * 255),
            g: Math.round(g * 255),
            b: Math.round(b * 255)
        };
    }

    rgbToHex(r, g, b) {
        return '#' + [r, g, b].map(x => {
            const hex = x.toString(16);
            return hex.length === 1 ? '0' + hex : hex;
        }).join('').toUpperCase();
    }

    hexToRgb(hex) {
        const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16)
        } : null;
    }

    rgbToHsb(r, g, b) {
        r /= 255;
        g /= 255;
        b /= 255;
        
        const max = Math.max(r, g, b);
        const min = Math.min(r, g, b);
        const diff = max - min;
        
        let h = 0;
        if (diff !== 0) {
            if (max === r) {
                h = ((g - b) / diff) % 6) * 60;
            } else if (max === g) {
                h = ((b - r) / diff + 2) * 60;
            } else {
                h = ((r - g) / diff + 4) * 60;
            }
        }
        if (h < 0) h += 360;
        
        const s = max === 0 ? 0 : diff / max;
        const v = max;
        
        return { h, s, v };
    }

    updateColor(hex, updateInputs = true) {
        this.currentColor = hex.toUpperCase();
        this.previewBtn.style.backgroundColor = this.currentColor;
        
        const rgb = this.hexToRgb(this.currentColor);
        if (!rgb) return;
        
        const hsb = this.rgbToHsb(rgb.r, rgb.g, rgb.b);
        this.hue = hsb.h;
        
        // Update main canvas
        this.drawMainCanvas(this.hue);
        
        // Update cursors
        const x = hsb.s * 200;
        const y = (1 - hsb.v) * 200;
        this.updateCursor(x, y);
        this.updateHueCursor((this.hue / 360) * 200);
        
        // Update inputs
        if (updateInputs) {
            if (this.hexInput) {
                this.hexInput.value = this.currentColor;
            }
            if (this.rgbR) {
                this.rgbR.value = rgb.r;
                this.rgbG.value = rgb.g;
                this.rgbB.value = rgb.b;
            }
            if (this.rgbRSlider) {
                this.rgbRSlider.value = rgb.r;
                this.rgbGSlider.value = rgb.g;
                this.rgbBSlider.value = rgb.b;
            }
        }
        
        // Callback
        if (this.options.onColorChange) {
            this.options.onColorChange(this.currentColor);
        }
    }

    updateCursor(x, y) {
        this.mainCursor.style.left = `${x}px`;
        this.mainCursor.style.top = `${y}px`;
    }

    updateHueCursor(y) {
        this.hueCursor.style.top = `${y}px`;
    }

    toggle() {
        this.isOpen ? this.close() : this.open();
    }

    open() {
        this.panel.style.display = 'block';
        this.isOpen = true;
    }

    close() {
        this.panel.style.display = 'none';
        this.isOpen = false;
    }

    getColor() {
        return this.currentColor;
    }

    setColor(color) {
        this.updateColor(color);
    }
}

// Export for use in other scripts
if (typeof module !== 'undefined' && module.exports) {
    module.exports = ColorPicker;
}

