import { state } from '../state.js';
import { SceneFeature } from './SceneFeature.js';
import sceneFeatureManager from './SceneFeatureManager.js';
import { showStandbyScreen } from './projection-screen.js';
import { MediaStorage } from '../core/media-storage.js';

export class MusicPlayer extends SceneFeature {
    constructor() {
        super();
        this.audioContext = null;
        this.analyser = null;
        this.source = null;
        this.dataArray = null;
        this.loudnessHistory = [];
        sceneFeatureManager.register(this);
    }

    init() {
        state.music.player = document.getElementById('audioPlayer');
        state.music.loudness = 0;
        state.music.isLoudEnough = false;

        const loadButton = document.getElementById('loadMusicButton');
        const fileInput = document.getElementById('musicFileInput');

        // Hide the big start button as we use ConfigUI now
        if (loadButton) loadButton.style.display = 'none';

        fileInput.addEventListener('change', (event) => {
            const file = event.target.files[0];
            if (file) {
                this.loadMusicFile(file);
                MediaStorage.saveMusic(file);
            }
        });

        state.music.player.addEventListener('ended', () => {
            this.stopParty();
            const uiContainer = document.getElementById('ui-container');
            if (uiContainer) uiContainer.style.display = 'flex'; // Show the button again
        });

        // Restore from storage
        MediaStorage.getMusic().then(file => {
            if (file) {
                this.loadMusicFile(file);
            }
        });
    }

    loadMusicFile(file) {
        // Setup Web Audio API if not already done
        if (!this.audioContext) {
            this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
            this.analyser = this.audioContext.createAnalyser();
            this.analyser.fftSize = 128; // Lower resolution is fine for loudness
            this.source = this.audioContext.createMediaElementSource(state.music.player);
            this.source.connect(this.analyser);
            this.analyser.connect(this.audioContext.destination);
            this.dataArray = new Uint8Array(this.analyser.frequencyBinCount);
        }

        // Update State
        const songName = file.name.replace(/\.[^/.]+$/, "");
        state.music.songTitle = songName;

        const url = URL.createObjectURL(file);
        state.music.player.src = url;

        // Update Config UI
        const configUI = sceneFeatureManager.features.find(f => f.constructor.name === 'ConfigUI');
        if (configUI) configUI.updateStatus();

        // Update Projection Screen with new song title
        showStandbyScreen();
    }

    startSequence() {
        const uiContainer = document.getElementById('ui-container');
        const configUILeft = document.getElementById('config-ui-left');
        const configUIRight = document.getElementById('config-ui-right');
        
        if (uiContainer) uiContainer.style.display = 'none';
        if (configUILeft) configUILeft.style.display = 'none';
        if (configUIRight) configUIRight.style.display = 'none';
        if (state.loadTapeButton) state.loadTapeButton.classList.add('hidden');

        showStandbyScreen();

        // Wait 5 seconds, then start the party
        setTimeout(() => {
            this.startParty();
        }, 5000);
    }

    startParty() {
        state.clock.start();
        state.music.player.play();
        document.getElementById('ui-container').style.display = 'none';
        state.partyStarted = true;

        // You could add BPM detection here in the future
        // For now, we use the fixed BPM

        // Trigger 'start' event for other features
        this.notifyFeatures('onPartyStart');
    }

    stopParty() {
        state.clock.stop();
        state.partyStarted = false;
        // Trigger 'end' event for other features
        this.notifyFeatures('onPartyEnd');
    }

    notifyFeatures(methodName) {
        sceneFeatureManager.features.forEach(feature => {
            if (typeof feature[methodName] === 'function') {
                feature[methodName]();
            }
        });
    }

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

        this.analyser.getByteFrequencyData(this.dataArray);

        // --- Calculate current loudness ---
        let sum = 0;
        for (let i = 0; i < this.dataArray.length; i++) {
            sum += this.dataArray[i];
        }
        const average = sum / this.dataArray.length;
        state.music.loudness = average / 255; // Normalize to 0-1 range

        // --- Track loudness over the last 2 seconds ---
        this.loudnessHistory.push(state.music.loudness);
        if (this.loudnessHistory.length > 120) { // Assuming ~60fps, 2 seconds of history
            this.loudnessHistory.shift();
        }

        // --- Determine if it's loud enough to jump ---
        const avgLoudness = this.loudnessHistory.reduce((a, b) => a + b, 0) / this.loudnessHistory.length;
        const quietThreshold = 0.1; // Adjust this value based on testing

        state.music.isLoudEnough = avgLoudness > quietThreshold;
    }
}

new MusicPlayer();