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

const minSwitchInterval = 2;
const maxSwitchInterval = 10;

export class CameraManager extends SceneFeature {
    constructor() {
        super();
        this.cameras = [];
        this.activeCameraIndex = 0;
        this.switchInterval = 10; // seconds
        this.lastSwitchTime = 0;
        sceneFeatureManager.register(this);
    }

    init() {
        // The main camera from init.js is our first camera
        const mainCamera = state.camera;
        mainCamera.fov = 20;
        const mainCameraSetup = {
            camera: mainCamera,
            type: 'dynamic',
            name: 'MainDynamicCamera',
            update: this.updateDynamicCamera, // Assign its update function
        };
        this.cameras.push(mainCameraSetup);

        // --- Static Camera 1: Left Aisle View ---
        const staticCam1 = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
        staticCam1.position.set(-5, 3, -13);
        staticCam1.lookAt(0, 2, -18); // Look at the stage
        this.cameras.push({
            camera: staticCam1,
            type: 'static',
            name: 'LeftAisleCam'
        });

        // --- Static Camera 2: Right Aisle View ---
        const staticCam2 = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100);
        staticCam2.position.set(5, 4, -6);
        staticCam2.lookAt(0, 1.5, -18); // Look at the stage
        this.cameras.push({
            camera: staticCam2,
            type: 'static',
            name: 'RightAisleCam'
        });

        // --- Static Camera 3: Far-Back view ---
        const staticCam3 = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 100);
        staticCam3.position.set(0, 3, 12);
        staticCam3.lookAt(0, 1.5, -20); // Look at the stage
        this.cameras.push({
            camera: staticCam3,
            type: 'static',
            name: 'BackCam'
        });

        // --- Static Camera 3: Back view ---
        const staticCam4 = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 100);
        staticCam4.position.set(0, 4, 0);
        staticCam4.lookAt(0, 1.5, -20); // Look at the stage
        this.cameras.push({
            camera: staticCam4,
            type: 'static',
            name: 'BackCam'
        });

        // make the main camera come up more often
        this.cameras.push(mainCameraSetup);

        // --- Add Debug Helpers ---
        if (state.debugCamera) {
            this.cameras.forEach(camData => {
                const helper = new THREE.CameraHelper(camData.camera);
                state.scene.add(helper);
            });
        }

        this.lastSwitchTime = state.clock.getElapsedTime();
        this.switchCamera(4);
    }

    // This is the logic moved from animate.js
    updateDynamicCamera(timeDiff) {
        if (!state.partyStarted) return;
        
        const globalTime = Date.now() * 0.0001;
        const lookAtTime = Date.now() * 0.0002;

        const baseX = 0, baseY = 3.6, baseZ = -5.0;
        const camAmplitude = new THREE.Vector3(1.0, 1.0, 6.0);

        const baseTargetX = 0, baseTargetY = 1.6, baseTargetZ = -30.0;
        const lookAmplitude = 8.0;

        const camOffsetX = Math.sin(globalTime * 3.1) * camAmplitude.x;
        const camOffsetY = Math.cos(globalTime * 2.5) * camAmplitude.y;
        const camOffsetZ = Math.cos(globalTime * 3.2) * camAmplitude.z;

        state.camera.position.x = baseX + camOffsetX;
        state.camera.position.y = baseY + camOffsetY;
        state.camera.position.z = baseZ + camOffsetZ;

        const lookOffsetX = Math.sin(lookAtTime * 1.5) * lookAmplitude;
        const lookOffsetZ = Math.cos(lookAtTime * 2.5) * lookAmplitude;
        const lookOffsetY = Math.cos(lookAtTime * 1.2) * lookAmplitude * 0.5;

        state.camera.lookAt(baseTargetX + lookOffsetX, baseTargetY + lookOffsetY, baseTargetZ + lookOffsetZ);
    }

    switchCamera(index) {
        if (index >= this.cameras.length || index < 0) return;

        this.activeCameraIndex = index;
        const newCam = this.cameras[this.activeCameraIndex].camera;

        // Copy properties from the new camera to the main state camera
        state.camera.position.copy(newCam.position);
        state.camera.rotation.copy(newCam.rotation);
        state.camera.fov = newCam.fov;
        state.camera.aspect = newCam.aspect;
        state.camera.near = newCam.near;
        state.camera.far = newCam.far;
        state.camera.updateProjectionMatrix();
    }

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

        // Handle camera switching
        if (state.partyStarted) {
            if (time > this.lastSwitchTime + this.switchInterval) {
                const newIndex = Math.floor(Math.random() * this.cameras.length);
                this.switchCamera(newIndex);
                this.lastSwitchTime = time;
                this.switchInterval = minSwitchInterval + Math.random() * (maxSwitchInterval - minSwitchInterval);
            }
        }

        // Update the currently active camera if it has an update function
        const activeCamData = this.cameras[this.activeCameraIndex];
        if (activeCamData.update) {
            activeCamData.update();
        }
    }

    onPartyStart() {
        // Start the camera switching timer only when the party starts
        this.lastSwitchTime = state.clock.getElapsedTime();
    }
}

new CameraManager();