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 - 1;
        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);

        // --- 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;
        torchGroup.add(pointLight);

        // --- Particle System for Fire ---
        const particleCount = 50;
        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);
        torchGroup.add(particleSystem);

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

    update(deltaTime) {
        this.torches.forEach(torch => {
            let measurePulse = 0;
            if (state.music) {
                measurePulse = state.music.measurePulse * 4.0; // Make flames jump higher
            }

            // --- Animate Particles ---
            const positions = torch.particles.geometry.attributes.position.array;
            let averageY = 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) {
                    // 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 + measurePulse;
                } else {
                    // Update position
                    positions[i * 3] += data.velocity.x * deltaTime;
                    positions[i * 3 + 1] += yVelocity * deltaTime;
                    positions[i * 3 + 2] += data.velocity.z * deltaTime;
                }
                averageY += positions[i * 3 + 1];
            }
            averageY = averageY / positions.length;
            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;
            }

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

new StageTorches();