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

export class StageLights extends SceneFeature {
    constructor() {
        super();
        this.lights = [];
        this.focusPoint = new THREE.Vector3(0, 0, -10);
        this.targetFocusPoint = new THREE.Vector3(0, 0, -10);
        this.lastChangeTime = 0;
        sceneFeatureManager.register(this);
    }

    init() {
        // 1. Create the Steel Beam
        const beamLength = 24;
        const beamGeo = new THREE.BoxGeometry(beamLength, 0.5, 0.5);
        const beamMat = new THREE.MeshStandardMaterial({ 
            color: 0x444444, 
            metalness: 0.9, 
            roughness: 0.4 
        });
        this.beam = new THREE.Mesh(beamGeo, beamMat);
        // Positioned high above the front of the stage area
        this.beam.position.set(0, 9, -14); 
        this.beam.castShadow = true;
        this.beam.receiveShadow = true;
        state.scene.add(this.beam);

        // 2. Create Spotlights
        const numLights = 8;
        const spacing = beamLength / numLights;

        // Geometry for the light fixture (par can style)
        const fixtureGeo = new THREE.CylinderGeometry(0.2, 0.3, 0.6);
        // Rotate geometry so -Y (bottom) points to +Z (lookAt direction)
        fixtureGeo.rotateX(-Math.PI / 2);

        const fixtureMat = new THREE.MeshStandardMaterial({ color: 0x111111 });
        const lensGeo = new THREE.CircleGeometry(0.18, 32);

        for (let i = 0; i < numLights; i++) {
            const x = -beamLength / 2 + spacing/2 + i * spacing;
            
            // Fixture Mesh
            const fixture = new THREE.Mesh(fixtureGeo, fixtureMat);
            fixture.position.set(x, 8.5, -14); // Match beam position
            state.scene.add(fixture);

            // Lens Mesh
            const lensMat = new THREE.MeshBasicMaterial({ color: 0xffffff });
            const lens = new THREE.Mesh(lensGeo, lensMat);
            lens.position.set(0, 0, 0.31);
            fixture.add(lens);

            // SpotLight
            const spotLight = new THREE.SpotLight(0xffffee, 0);
            spotLight.position.copy(fixture.position);
            spotLight.angle = Math.PI / 6;
            spotLight.penumbra = 0.3;
            spotLight.decay = 1.5;
            spotLight.distance = 60;
            spotLight.castShadow = true;
            spotLight.shadow.bias = -0.0001;
            spotLight.shadow.mapSize.width = 512;
            spotLight.shadow.mapSize.height = 512;
            
            // Target Object
            const target = new THREE.Object3D();
            state.scene.add(target);
            spotLight.target = target;

            state.scene.add(spotLight);
            
            this.lights.push({ 
                light: spotLight, 
                fixture: fixture, 
                lens: lens,
                target: target,
                baseX: x 
            });
        }

        // Initialize static random state for pre-party
        this.staticColor = new THREE.Color().setHSL(Math.random(), 0.8, 0.5);
        this.focusPoint.set((Math.random() - 0.5) * 20, Math.random() * 2, -10 + (Math.random() - 0.5) * 10);
        this.targetFocusPoint.copy(this.focusPoint);
    }

    update(deltaTime) {
        const time = state.clock.getElapsedTime();

        if (!state.partyStarted) {
            this.lights.forEach((item) => {
                const targetX = this.focusPoint.x + (item.baseX * 0.2);
                item.target.position.set(targetX, this.focusPoint.y, this.focusPoint.z);
                item.fixture.lookAt(targetX, this.focusPoint.y, this.focusPoint.z);
                item.light.intensity = 30;
                if (this.staticColor) {
                    item.light.color.copy(this.staticColor);
                    item.lens.material.color.copy(this.staticColor);
                }
            });
            return;
        }
        
        // Change target area logic
        let shouldChange = false;
        if (time < this.lastChangeTime) this.lastChangeTime = time;

        if (state.music && state.partyStarted) {
            // Change on the measure (every 4 beats) if enough time has passed
            if (state.music.measurePulse > 0.5 && time - this.lastChangeTime > 1.5) {
                shouldChange = true;
            }
        } else if (time - this.lastChangeTime > 3.0) {
            shouldChange = true;
        }

        if (shouldChange) {
            this.lastChangeTime = time;
            
            // Randomly pick a zone: Stage or Dance Floor
            if (Math.random() < 0.4) {
                // Stage Area (Z: -20 to -10)
                this.targetFocusPoint.set((Math.random() - 0.5) * 15, 1, -15 + (Math.random() - 0.5) * 5);
            } else {
                // Dance Floor / Guests (Z: -5 to 15)
                this.targetFocusPoint.set((Math.random() - 0.5) * 20, 0, 5 + (Math.random() - 0.5) * 15);
            }
        }

        // Smoothly move the focus point
        this.focusPoint.lerp(this.targetFocusPoint, deltaTime * 2.0);

        // Update each light
        let intensity = state.music ? 20 + state.music.beatIntensity * 150 : 50;
        if (state.blackoutMode) {
            intensity = 0;
        }
        
        const spread = 0.2 + (state.music ? state.music.beatIntensity * 0.4 : 0);
        const bounce = state.music ? state.music.beatIntensity * 0.5 : 0;
        const palette = state.config.lightBarColors;

        this.lights.forEach((item, index) => {
            // Converge lights on focus point, but keep slight X offset for spread
            const targetX = this.focusPoint.x + (item.baseX * spread);
            
            item.target.position.set(targetX, this.focusPoint.y + bounce, this.focusPoint.z);
            item.fixture.lookAt(targetX, this.focusPoint.y, this.focusPoint.z);
            item.light.intensity = intensity;
            
            if (palette && palette.length > 0) {
                const colorIndex = Math.floor(time * 0.5) % palette.length;
                const c = new THREE.Color(palette[colorIndex]);
                item.light.color.copy(c);
                item.lens.material.color.copy(c);
            } else {
                const hue = (time * 0.2) % 1;
                const c = new THREE.Color().setHSL(hue, 0.8, 0.5);
                item.light.color.copy(c);
                item.lens.material.color.copy(c);
            }
        });
    }
}

new StageLights();