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

const lightPositionBaseY = 1.2;

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

    init() {
        // --- Stage Dimensions for positioning ---
        const length = 40;
        const naveWidth = 12;
        const stageWidth = naveWidth - 2;
        const stageHeight = 1.5;
        const stageDepth = 5;

        const torchPositions = [
            new THREE.Vector3(-stageWidth / 2, stageHeight, -length / 2 + 0.5),
            new THREE.Vector3(stageWidth / 2, stageHeight, -length / 2 + 0.5),
            new THREE.Vector3(-stageWidth / 2, stageHeight, -length / 2 + stageDepth - 0.5),
            new THREE.Vector3(stageWidth / 2, stageHeight, -length / 2 + stageDepth - 0.5),
        ];

        torchPositions.forEach(pos => {
            const torch = this.createTorch(pos);
            this.torches.push(torch);
            state.scene.add(torch.group);
        });
    }

    createTorch(position) {
        const torchGroup = new THREE.Group();
        torchGroup.position.copy(position);
        torchGroup.visible = state.config.torchesEnabled;

        // --- Torch Holder ---
        const holderMaterial = new THREE.MeshStandardMaterial({ color: 0x333333, roughness: 0.6, metalness: 0.5 });
        const holderGeo = new THREE.CylinderGeometry(0.1, 0.15, 1.0, 12);
        const holderMesh = new THREE.Mesh(holderGeo, holderMaterial);
        holderMesh.position.y = 0.5;
        holderMesh.castShadow = true;
        holderMesh.receiveShadow = true;
        torchGroup.add(holderMesh);

        // --- Point Light ---
        const pointLight = new THREE.PointLight(0xffaa44, 2.5, 8);
        pointLight.position.y = lightPositionBaseY;
        pointLight.castShadow = true;
        pointLight.shadow.mapSize.width = 128;
        pointLight.shadow.mapSize.height = 128;
        pointLight.visible = false;
        torchGroup.add(pointLight);

        // --- Particle System for Fire ---
        const particleCount = 100;
        const particles = new THREE.BufferGeometry();
        const positions = [];
        const particleData = [];

        const sparkTexture = state.loader.load(sparkTextureUrl);
        const particleMaterial = new THREE.PointsMaterial({
            map: sparkTexture,
            color: 0xffaa00,
            size: 0.5,
            blending: THREE.AdditiveBlending,
            transparent: true,
            depthWrite: false,
        });

        for (let i = 0; i < particleCount; i++) {
            positions.push(0, 1, 0);
            particleData.push({
                velocity: new THREE.Vector3((Math.random() - 0.5) * 0.2, Math.random() * 1.5, (Math.random() - 0.5) * 0.2),
                life: Math.random() * 1.0,
            });
        }
        particles.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
        const particleSystem = new THREE.Points(particles, particleMaterial);
        particleSystem.visible = false;
        torchGroup.add(particleSystem);

        return { group: torchGroup, light: pointLight, particles: particleSystem, particleData: particleData };
    }

    resetParticles(torch) {
        const positions = torch.particles.geometry.attributes.position.array;
        for (let i = 0; i < torch.particleData.length; i++) {
            const data = torch.particleData[i];
            // Reset particle
            positions[i * 3] = 0;
            positions[i * 3 + 1] = 1;
            positions[i * 3 + 2] = 0;
            data.life = Math.random() * 1.0;
            data.velocity.y = Math.random() * 1.5;
        }
        torch.particles.geometry.attributes.position.needsUpdate = true;
    }

    update(deltaTime) {
        const configEnabled = state.config.torchesEnabled;
        this.torches.forEach(torch => {
            if (torch.group.visible !== configEnabled) torch.group.visible = configEnabled;
        });

        if (!configEnabled) return;

        const fireActive = !state.blackoutMode && !(!state.partyStarted && state.music.isLoudEnough);

        this.torches.forEach(torch => {
            if (torch.light.visible !== fireActive) torch.light.visible = fireActive;
            if (!torch.particles.visible) torch.particles.visible = true;

            let measurePulse = 0;
            if (state.music) {
                measurePulse = state.music.measurePulse * 2.0; // Make flames jump higher
            }
            if (state.music.isLoudEnough) {
                measurePulse += 2;
            }

            // --- Animate Particles ---
            const positions = torch.particles.geometry.attributes.position.array;
            let averageY = 0;
            let activeParticleCount = 0;
            for (let i = 0; i < torch.particleData.length; i++) {
                const data = torch.particleData[i];
                data.life -= deltaTime;
                const yVelocity = data.velocity.y;
                if (data.life <= 0 || positions[i * 3 + 1] < 0) {
                    if (fireActive) {
                        // Reset particle
                        positions[i * 3] = (Math.random() - 0.5) * 0.2;
                        positions[i * 3 + 1] = 1;
                        positions[i * 3 + 2] = (Math.random() - 0.5) * 0.2;
                        data.life = Math.random() * 1.0;
                        data.velocity.y = Math.random() * 1.2 + measurePulse;
                    } else {
                        // Stop producing: move out of view
                        positions[i * 3 + 1] = -100;
                    }
                } else {
                    // Update position
                    positions[i * 3] += data.velocity.x * deltaTime;
                    positions[i * 3 + 1] += yVelocity * deltaTime;
                    positions[i * 3 + 2] += data.velocity.z * deltaTime;
                }
                if (positions[i * 3 + 1] > -50) {
                    averageY += positions[i * 3 + 1];
                    activeParticleCount++;
                }
            }
            averageY = activeParticleCount > 0 ? averageY / activeParticleCount : 0;
            torch.particles.geometry.attributes.position.needsUpdate = true;

            // --- Flicker Light ---
            const baseIntensity = 2.0;
            const flicker = Math.random() * 0.6;
            let beatPulse = 0;
            if (state.music) {
                beatPulse = state.music.beatIntensity * 1.5;
                if (state.music.isLoudEnough) {
                    beatPulse += 2;
                }
            }

            torch.light.intensity = baseIntensity + flicker + beatPulse;
            torch.light.position.y = lightPositionBaseY + averageY;
        });
    }

    onPartyStart() {
        this.torches.forEach(torch => {
            if (state.config.torchesEnabled) {
                torch.group.visible = true;
                torch.light.visible = true;
                torch.particles.visible = true;
                this.resetParticles(torch);
            } else {
                torch.group.visible = false;
            }
        });
    }

    onPartyEnd() {
        this.torches.forEach(torch => {
        });
    }
}

new StageTorches();