import * as THREE from 'three';
import { state } from '../state.js';
import { SceneFeature } from './SceneFeature.js';
import sceneFeatureManager from './SceneFeatureManager.js';

export class MusicConsole extends SceneFeature {
    constructor() {
        super();
        this.lights = [];
        sceneFeatureManager.register(this);
    }

    init() {
        // Stage Y top is 1.5
        const stageY = 1.5;
        const consoleWidth = 4.0;
        const consoleDepth = 0.8;
        const consoleHeight = 1.2; 

        const group = new THREE.Group();
        // Position on stage, centered
        group.position.set(0, stageY, -16.5); 
        state.scene.add(group);
        this.group = group;
        this.group.visible = state.config.consoleEnabled;

        // 1. The Stand/Table Body
        const standGeo = new THREE.BoxGeometry(consoleWidth, consoleHeight, consoleDepth);
        const standMat = new THREE.MeshStandardMaterial({ 
            color: 0x1a1a1a, 
            roughness: 0.3, 
            metalness: 0.6 
        });
        const stand = new THREE.Mesh(standGeo, standMat);
        stand.position.y = consoleHeight / 2;
        stand.castShadow = true;
        stand.receiveShadow = true;
        group.add(stand);

        // 2. Control Surface (Top Plate)
        const topGeo = new THREE.BoxGeometry(consoleWidth + 0.1, 0.05, consoleDepth + 0.1);
        const topMat = new THREE.MeshStandardMaterial({ color: 0x050505, roughness: 0.8 });
        const topPlate = new THREE.Mesh(topGeo, topMat);
        topPlate.position.y = consoleHeight + 0.025;
        topPlate.receiveShadow = true;
        group.add(topPlate);

        const surfaceY = consoleHeight + 0.05;

        // 3. Knobs (Left side)
        const knobGeo = new THREE.CylinderGeometry(0.015, 0.015, 0.02, 12);
        const knobMat = new THREE.MeshStandardMaterial({ color: 0xcccccc, metalness: 0.8, roughness: 0.2 });
        const tinyLedGeo = new THREE.CircleGeometry(0.005, 8);
        tinyLedGeo.rotateX(-Math.PI / 2);
        
        for(let row=0; row<4; row++) {
            for(let col=0; col<16; col++) {
                const knob = new THREE.Mesh(knobGeo, knobMat);
                const x = -consoleWidth/2 + 0.3 + (col * 0.06);
                const z = -0.25 + (row * 0.08);
                knob.position.set(x, surfaceY + 0.01, z);
                group.add(knob);

                // Add tiny LED next to some knobs
                if (Math.random() > 0.5) {
                    const ledMat = new THREE.MeshBasicMaterial({ color: 0x222222 });
                    const led = new THREE.Mesh(tinyLedGeo, ledMat);
                    led.position.set(x + 0.02, surfaceY + 0.001, z + 0.02);
                    group.add(led);
                    
                    this.lights.push({
                        mesh: led,
                        onColor: new THREE.Color().setHSL(Math.random(), 1.0, 0.5),
                        offColor: new THREE.Color(0x222222),
                        active: false,
                        nextToggle: Math.random()
                    });
                }
            }
        }

        // 4. Sliders (Middle)
        const sliderTrackGeo = new THREE.BoxGeometry(0.01, 0.005, 0.25);
        const sliderHandleGeo = new THREE.BoxGeometry(0.025, 0.03, 0.015);
        const trackMat = new THREE.MeshBasicMaterial({ color: 0x111111 });
        const handleMat = new THREE.MeshStandardMaterial({ color: 0xffffff });

        for(let i=0; i<24; i++) {
            const x = -0.5 + (i * 0.05);
            
            const track = new THREE.Mesh(sliderTrackGeo, trackMat);
            track.position.set(x, surfaceY, 0.1);
            group.add(track);

            const handle = new THREE.Mesh(sliderHandleGeo, handleMat);
            // Randomize slider positions slightly
            const slidePos = (Math.random() - 0.5) * 0.2;
            handle.position.set(x, surfaceY + 0.015, 0.1 + slidePos);
            group.add(handle);

            // LED above slider
            const ledMat = new THREE.MeshBasicMaterial({ color: 0x222222 });
            const led = new THREE.Mesh(tinyLedGeo, ledMat);
            led.position.set(x, surfaceY + 0.001, -0.05);
            group.add(led);
            
            this.lights.push({
                mesh: led,
                onColor: new THREE.Color().setHSL(Math.random(), 1.0, 0.5),
                offColor: new THREE.Color(0x222222),
                active: false,
                nextToggle: Math.random()
            });
        }

        // 5. Blinky Lights (Right side grid)
        const lightGeo = new THREE.PlaneGeometry(0.03, 0.03);
        lightGeo.rotateX(-Math.PI / 2); // Lay flat
        
        const rows = 8;
        const cols = 16;
        
        for(let r=0; r<rows; r++) {
            for(let c=0; c<cols; c++) {
                const lightMat = new THREE.MeshBasicMaterial({ color: 0x222222 }); 
                const lightMesh = new THREE.Mesh(lightGeo, lightMat);
                
                const x = consoleWidth/2 - 1.0 + (c * 0.05);
                const z = -0.25 + (r * 0.05);
                
                lightMesh.position.set(x, surfaceY + 0.01, z);
                group.add(lightMesh);
                
                this.lights.push({
                    mesh: lightMesh,
                    // Assign random colors (Red, Green, Blue, Amber)
                    onColor: new THREE.Color().setHSL(Math.random(), 1.0, 0.5),
                    offColor: new THREE.Color(0x222222),
                    active: false,
                    nextToggle: Math.random()
                });
            }
        }

        // 6. Front LED Array (InstancedMesh)
        const ledRows = 10;
        const ledCols = 60;
        this.ledRows = ledRows;
        this.ledCols = ledCols;
        const ledCount = ledRows * ledCols;
        
        const ledDisplayGeo = new THREE.PlaneGeometry(0.04, 0.04);
        const ledDisplayMat = new THREE.MeshBasicMaterial({ color: 0xffffff });
        this.frontLedMesh = new THREE.InstancedMesh(ledDisplayGeo, ledDisplayMat, ledCount);
        
        const dummy = new THREE.Object3D();
        let idx = 0;
        
        const spacing = 0.06;
        const gridWidth = ledCols * spacing;
        const gridHeight = ledRows * spacing;
        
        // Center on the front face of the stand
        const startX = -gridWidth / 2 + spacing / 2;
        const startY = (consoleHeight / 2) - gridHeight / 2 + spacing / 2;
        const zPos = consoleDepth / 2 + 0.01; // Slightly in front of the stand
        
        for(let r=0; r<ledRows; r++) {
            for(let c=0; c<ledCols; c++) {
                dummy.position.set(startX + c * spacing, startY + r * spacing, zPos);
                dummy.updateMatrix();
                this.frontLedMesh.setMatrixAt(idx, dummy.matrix);
                this.frontLedMesh.setColorAt(idx, new THREE.Color(0x000000));
                idx++;
            }
        }
        this.frontLedMesh.instanceMatrix.needsUpdate = true;
        if (this.frontLedMesh.instanceColor) this.frontLedMesh.instanceColor.needsUpdate = true;
        group.add(this.frontLedMesh);
    }

    update(deltaTime) {
        if (!state.partyStarted || !state.music) return;

        const time = state.clock.getElapsedTime();
        const beatIntensity = state.music.beatIntensity;

        this.lights.forEach(light => {
            if (state.blackoutMode) {
                light.mesh.material.color.copy(light.offColor);
                return;
            }

            if (time > light.nextToggle) {
                // Toggle state
                light.active = !light.active;
                
                // Determine next toggle time based on music intensity
                // Higher intensity = faster toggles
                const speed = 0.1 + (1.0 - beatIntensity) * 0.5; 
                light.nextToggle = time + speed + Math.random() * 0.2;
            }

            if (light.active) {
                light.mesh.material.color.copy(light.onColor);
                // Pulse brightness with beat
                light.mesh.material.color.multiplyScalar(1 + beatIntensity * 2);
            } else {
                light.mesh.material.color.copy(light.offColor);
            }
        });

        // Update Front LED Array
        if (this.frontLedMesh) {
            if (!state.config.consoleRGBEnabled || state.blackoutMode) {
                this.frontLedMesh.visible = false;
                return;
            }
            this.frontLedMesh.visible = true;
            const color = new THREE.Color();
            let idx = 0;
            
            for(let r=0; r<this.ledRows; r++) {
                for(let c=0; c<this.ledCols; c++) {
                    const u = c / this.ledCols;
                    const v = r / this.ledRows;
                    
                    // Dynamic wave pattern
                    const wave1 = Math.sin(u * 12 + time * 3);
                    const wave2 = Math.cos(v * 8 - time * 2);
                    const wave3 = Math.sin((u + v) * 5 + time * 5);
                    
                    const intensity = (wave1 + wave2 + wave3) / 3 * 0.5 + 0.5;
                    
                    // Color palette shifting
                    const palette = state.config.lightBarColors;
                    if (palette && palette.length > 0) {
                        const drive = (time * 0.1 + u * 0.3 + intensity * 0.2);
                        const paletteIndex = Math.floor(((drive % 1) + 1) % 1 * palette.length);
                        color.set(palette[paletteIndex]);
                        
                        const light = intensity * (0.1 + beatIntensity * 0.9);
                        color.multiplyScalar(light);
                    } else {
                        const hue = (time * 0.1 + u * 0.3 + intensity * 0.2) % 1;
                        const sat = 0.9;
                        const light = intensity * (0.1 + beatIntensity * 0.9); // Pulse brightness with beat
                        color.setHSL(hue, sat, light);
                    }
                    this.frontLedMesh.setColorAt(idx, color);
                    idx++;
                }
            }
            if (this.frontLedMesh.instanceColor) this.frontLedMesh.instanceColor.needsUpdate = true;
        }
    }
}

new MusicConsole();