import { SceneFeature } from './SceneFeature.js';
import sceneFeatureManager from './SceneFeatureManager.js';
import { state } from '../state.js';

export class DebugPanel extends SceneFeature {
    constructor() {
        super();
        this.frames = 0;
        this.timeAccumulator = 0;
        this.fpsElement = null;
        this.textElement = null;
        this.canvas = null;
        this.ctx = null;
        this.history = [];
        this.memTextElement = null;
        this.memCanvas = null;
        this.memCtx = null;
        this.memHistory = [];
        this.musicTextElement = null;
        this.musicCanvas = null;
        this.musicCtx = null;
        this.spectrumTextElement = null;
        this.spectrumCanvas = null;
        this.spectrumCtx = null;
        this.musicHistory = [];
        sceneFeatureManager.register(this);
    }

    init() {
        const graphWidth = 150;
        const graphHeight = 80;

        // Create the FPS display container
        this.fpsElement = document.createElement('div');
        Object.assign(this.fpsElement.style, {
            position: 'absolute',
            top: '0',
            right: '0',
            zIndex: '10000',
            padding: '5px',
            background: 'rgba(0, 0, 0, 0.5)',
            pointerEvents: 'none',
            // Allow pointer events on the panel itself if we want to interact, but usually debug panels are pass-through
            userSelect: 'none', 
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'flex-end'
        });

        // Text Display
        this.textElement = document.createElement('div');
        Object.assign(this.textElement.style, {
            color: '#00ff00',
            fontFamily: 'monospace',
            fontSize: '16px',
            fontWeight: 'bold',
            marginBottom: '2px'
        });
        this.textElement.innerText = 'FPS: --';
        this.fpsElement.appendChild(this.textElement);

        // Graph Canvas
        this.canvas = document.createElement('canvas');
        this.canvas.width = graphWidth;
        this.canvas.height = 40;
        Object.assign(this.canvas.style, {
            width: graphWidth + 'px',
            height: '40px',
            background: '#222',
            border: '1px solid #444'
        });
        this.ctx = this.canvas.getContext('2d');
        this.fpsElement.appendChild(this.canvas);

        // Memory Text Display
        this.memTextElement = document.createElement('div');
        Object.assign(this.memTextElement.style, {
            color: '#00ffff',
            fontFamily: 'monospace',
            fontSize: '16px',
            fontWeight: 'bold',
            marginBottom: '2px',
            marginTop: '5px'
        });
        this.memTextElement.innerText = 'MEM: --';
        this.fpsElement.appendChild(this.memTextElement);

        // Memory Graph Canvas
        this.memCanvas = document.createElement('canvas');
        this.memCanvas.width = graphWidth;
        this.memCanvas.height = 40;
        Object.assign(this.memCanvas.style, {
            width: graphWidth + 'px',
            height: '40px',
            background: '#222',
            border: '1px solid #444'
        });
        this.memCtx = this.memCanvas.getContext('2d');
        this.fpsElement.appendChild(this.memCanvas);

        // Music Text Display
        this.musicTextElement = document.createElement('div');
        Object.assign(this.musicTextElement.style, {
            color: '#ff00ff',
            fontFamily: 'monospace',
            fontSize: '16px',
            fontWeight: 'bold',
            marginBottom: '2px',
            marginTop: '5px'
        });
        this.musicTextElement.innerText = 'MUSIC';
        this.fpsElement.appendChild(this.musicTextElement);

        // Music Graph Canvas
        this.musicCanvas = document.createElement('canvas');
        this.musicCanvas.width = graphWidth;
        this.musicCanvas.height = graphHeight;
        Object.assign(this.musicCanvas.style, {
            width: graphWidth + 'px',
            height: graphHeight + 'px',
            background: '#222',
            border: '1px solid #444'
        });
        this.musicCtx = this.musicCanvas.getContext('2d');
        this.fpsElement.appendChild(this.musicCanvas);

        // Spectrum Text Display
        this.spectrumTextElement = document.createElement('div');
        Object.assign(this.spectrumTextElement.style, {
            color: '#ffff00',
            fontFamily: 'monospace',
            fontSize: '16px',
            fontWeight: 'bold',
            marginBottom: '2px',
            marginTop: '5px'
        });
        this.spectrumTextElement.innerText = 'SPECTRUM';
        this.fpsElement.appendChild(this.spectrumTextElement);

        // Spectrum Graph Canvas
        this.spectrumCanvas = document.createElement('canvas');
        this.spectrumCanvas.width = graphWidth;
        this.spectrumCanvas.height = 60;
        Object.assign(this.spectrumCanvas.style, {
            width: graphWidth + 'px',
            height: '60px',
            background: '#222',
            border: '1px solid #444'
        });
        this.spectrumCtx = this.spectrumCanvas.getContext('2d');
        this.fpsElement.appendChild(this.spectrumCanvas);

        document.body.appendChild(this.fpsElement);
        
        this.history = new Array(this.canvas.width).fill(0);
        this.memHistory = new Array(this.memCanvas.width).fill(0);
        this.musicHistory = new Array(this.musicCanvas.width).fill({l:0, la:0, low:0, lla:0, high:0, b:0, lt:0, qt:0, m:0.5, bo: false, al: 0, bt: 0});

        // Initialize visibility based on config
        if (state.config) {
            this.setVisibility(state.config.debugPanelEnabled);
        }
    }

    update(deltaTime) {
        this.frames++;
        this.timeAccumulator += deltaTime;

        const segment = 0.25;
        if (this.timeAccumulator >= segment) {
            const fps = Math.round(this.frames / this.timeAccumulator);
            if (this.textElement) this.textElement.innerText = `FPS: ${fps}`;
            
            // Update Graph
            this.history.push(fps);
            if (this.history.length > this.canvas.width) {
                this.history.shift();
            }
            this.drawGraph();

            // Update Memory
            if (performance && performance.memory) {
                const mem = performance.memory.usedJSHeapSize / 1048576; // MB
                if (this.memTextElement) this.memTextElement.innerText = `MEM: ${Math.round(mem)} MB`;
                
                this.memHistory.push(mem);
                if (this.memHistory.length > this.memCanvas.width) {
                    this.memHistory.shift();
                }
                this.drawMemGraph();
            } else if (state.renderer) {
                // Fallback for Firefox: Visualize Scene Complexity (Triangles)
                const tris = state.renderer.info.render.triangles;
                const kTris = Math.round(tris / 1000);
                if (this.memTextElement) this.memTextElement.innerText = `TRIS: ${kTris}k`;

                this.memHistory.push(kTris);
                if (this.memHistory.length > this.memCanvas.width) {
                    this.memHistory.shift();
                }
                this.drawMemGraph();
            } else {
                 if (this.memTextElement) this.memTextElement.innerText = `MEM: N/A`;
            }

            this.frames = 0;
            this.timeAccumulator = 0;
        }

        // Update Music Graph (Every frame for smoothness)
        if (state.music) {
            const loudness = state.music.loudness || 0;
            const loudnessAvg = state.music.loudnessAverage || 0;
            const lows = state.music.loudnessLows || 0;
            const lowsAvg = state.music.loudnessLowsAverage || 0;
            const avgLoudness = state.music.averageLoudness || 0;
            const highs = state.music.loudnessHighs || 0;
            const beat = state.music.beatIntensity || 0;
            const beatThreshold = state.music.beatThreshold || 0;
            const thresholds = state.music.thresholds || { loud: 0, quiet: 0 };
            let modeVal = 0.5;
            if (state.music.mode === 'Loud') modeVal = 1.0;
            else if (state.music.mode === 'Quiet') modeVal = 0.0;
            
            this.musicHistory.push({ l: loudness, la: loudnessAvg, low: lows, lla: lowsAvg, high: highs, b: beat, lt: thresholds.loud, qt: thresholds.quiet, m: modeVal, bo: state.blackoutMode, al: avgLoudness, bt: beatThreshold });
            if (this.musicHistory.length > this.musicCanvas.width) {
                this.musicHistory.shift();
            }
            this.drawMusicGraph();
            this.drawSpectrumGraph();
            
            if (this.musicTextElement) {
                this.musicTextElement.innerText = `Volume: ${loudness.toFixed(2)}\nBPM: ${state.music.bpm}`;
            }
        }
    }

    setVisibility(visible) {
        if (!this.fpsElement) return;
        this.fpsElement.style.display = visible ? 'flex' : 'none';
    }

    drawGraph() {
        if (!this.ctx) return;
        const ctx = this.ctx;
        const w = this.canvas.width;
        const h = this.canvas.height;
        const maxFps = 70; 

        ctx.clearRect(0, 0, w, h);

        // Draw 60 FPS reference line
        const y60 = h - (60 / maxFps) * h;
        ctx.beginPath();
        ctx.strokeStyle = '#555';
        ctx.moveTo(0, y60);
        ctx.lineTo(w, y60);
        ctx.stroke();

        // Draw Graph
        ctx.beginPath();
        ctx.strokeStyle = '#00ff00';
        ctx.lineWidth = 1.5;
        
        for (let i = 0; i < this.history.length; i++) {
            const val = this.history[i];
            const x = i;
            const y = h - (val / maxFps) * h;
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();
    }

    drawMemGraph() {
        if (!this.memCtx) return;
        const ctx = this.memCtx;
        const w = this.memCanvas.width;
        const h = this.memCanvas.height;
        // Auto-scale max memory
        const maxMem = Math.max(...this.memHistory, 100) * 1.1; 

        ctx.clearRect(0, 0, w, h);

        // Draw Graph
        ctx.beginPath();
        ctx.strokeStyle = '#00ffff';
        ctx.lineWidth = 1.5;
        
        for (let i = 0; i < this.memHistory.length; i++) {
            const val = this.memHistory[i];
            const x = i;
            const y = h - (val / maxMem) * h;
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();
    }

    drawMusicGraph() {
        if (!this.musicCtx) return;
        const ctx = this.musicCtx;
        const w = this.musicCanvas.width;
        const h = this.musicCanvas.height;

        ctx.clearRect(0, 0, w, h);

        // Draw Lows (Brown)
        ctx.beginPath();
        ctx.strokeStyle = '#D2691E'; // Chocolate Brown
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].low !== undefined ? this.musicHistory[i].low : 0;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw Lows Avg (Darker Brown)
        ctx.beginPath();
        ctx.strokeStyle = '#8B4513'; // Saddle Brown
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].lla !== undefined ? this.musicHistory[i].lla : 0;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw All (Blue)
        ctx.beginPath();
        ctx.strokeStyle = '#66aaff'; // Visible Blue
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].l;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw Highs (White)
        ctx.beginPath();
        ctx.strokeStyle = '#ffffff';
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].high !== undefined ? this.musicHistory[i].high : 0;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw All Avg (Blue)
        ctx.beginPath();
        ctx.strokeStyle = '#8866ff';
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].la;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw Average Loudness (Pink)
        ctx.beginPath();
        ctx.strokeStyle = '#FF69B4'; // HotPink
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].al !== undefined ? this.musicHistory[i].al : 0;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw Beat Intensity (Magenta)
        ctx.beginPath();
        ctx.strokeStyle = '#ff00ff';
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].b;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw Beat Threshold (Cyan)
        ctx.beginPath();
        ctx.strokeStyle = '#00ffff';
        ctx.lineWidth = 1;
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].bt !== undefined ? this.musicHistory[i].bt : 0;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();

        // Draw Active Threshold (Green for Loud/Blackout, Red for Quiet/Normal)
        ctx.lineWidth = 1;
        
        for (let i = 0; i < this.musicHistory.length - 1; i++) {
            const curr = this.musicHistory[i];
            const next = this.musicHistory[i+1];
            
            ctx.beginPath();
            
            if (curr.bo) {
                // Blackout Mode: Draw Loud Threshold (Green Dashed)
                ctx.strokeStyle = '#00ff00';
                ctx.setLineDash([2, 2]);
                ctx.moveTo(i, h - (curr.lt * h));
                ctx.lineTo(i + 1, h - (next.lt * h));
            } else {
                // Normal Mode: Draw Quiet Threshold (Red Solid)
                ctx.strokeStyle = '#ff0000';
                ctx.setLineDash([]);
                ctx.moveTo(i, h - (curr.qt * h));
                ctx.lineTo(i + 1, h - (next.qt * h));
            }
            ctx.stroke();
        }

        // Draw Mode (Yellow)
        ctx.beginPath();
        ctx.strokeStyle = '#ffff00';
        ctx.setLineDash([1, 2]);
        for (let i = 0; i < this.musicHistory.length; i++) {
            const val = this.musicHistory[i].m !== undefined ? this.musicHistory[i].m : 0.5;
            const x = i;
            const y = h - (val * h);
            if (i === 0) ctx.moveTo(x, y);
            else ctx.lineTo(x, y);
        }
        ctx.stroke();
        ctx.setLineDash([]); // Reset dash
    }

    drawSpectrumGraph() {
        if (!this.spectrumCtx || !state.music || !state.music.frequencyData) return;
        const ctx = this.spectrumCtx;
        const w = this.spectrumCanvas.width;
        const h = this.spectrumCanvas.height;
        const data = state.music.frequencyData;
        const bufferLength = data.length;

        ctx.clearRect(0, 0, w, h);

        const barWidth = w / bufferLength;
        let x = 0;

        for(let i = 0; i < bufferLength; i++) {
            const val = (data[i] / 255);
            const barHeight = val * h;
            const hue = (i / bufferLength) * 260; // Red to Purple
            ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
            ctx.fillRect(x, h - barHeight, barWidth + 1, barHeight);
            x += barWidth;
        }
    }
}
new DebugPanel();