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';
import { showToast } from '../core/ui-utils.js';

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

    init() {
        state.music.player = document.getElementById('audioPlayer');
        if (!state.music.player) {
            state.music.player = document.createElement('audio');
            state.music.player.id = 'audioPlayer';
            document.body.appendChild(state.music.player);
        }
        state.music.loudness = 0;
        state.music.loudnessAverage = 0;
        const loadButton = document.getElementById('loadMusicButton');
        
        let fileInput = document.getElementById('musicFileInput');
        if (!fileInput) {
            fileInput = document.createElement('input');
            fileInput.id = 'musicFileInput';
            fileInput.type = 'file';
            fileInput.accept = 'audio/*';
            fileInput.style.display = 'none';
            document.body.appendChild(fileInput);
        }
        
        // Reset value to allow re-selecting the same file
        fileInput.onclick = () => { fileInput.value = ''; };

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

        fileInput.onchange = (event) => {
            const file = event.target.files[0];
            if (file) {
                console.info(`[MusicPlayer] File selected from input: ${file.name} (${file.size} bytes)`);
                if (file.size === 0) {
                    console.warn('[MusicPlayer] Selected file is empty (0 bytes). Check if file is a cloud placeholder or locked.');
                    showToast(`Error: "${file.name}" is empty (0 bytes). Looks like the browser can't access it.`, 'error');
                    return;
                }
                this.loadMusicFile(file);
                MediaStorage.saveMusic(file).then(() => showToast(`Loaded "${file.name}"`, 'success'))
                    .catch(e => {
                        console.warn('[MusicPlayer] Failed to save music:', e);
                        showToast('Warning: Failed to save song to storage.', 'warning');
                    });
            }
        };

        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) {
                console.info(`[MusicPlayer] Restored music from storage: ${file.name} (${file.size} bytes)`);
                this.loadMusicFile(file);
            }
        });
    }

    loadMusicFile(file) {
        if (!file || file.size === 0) {
            console.warn('[MusicPlayer] loadMusicFile called with invalid or empty file.');
            return;
        }

        // 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 = 1024; // Higher resolution for better bass detection
            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);
            state.music.frequencyData = this.dataArray;
        }

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

        if (state.music.player.src && state.music.player.src.startsWith('blob:')) {
            URL.revokeObjectURL(state.music.player.src);
        }

        const url = URL.createObjectURL(file);
        state.music.player.src = url;
        console.info(`[MusicPlayer] Audio source set to blob URL: ${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() {
        if (this.audioContext && this.audioContext.state === 'suspended') {
            this.audioContext.resume();
        }

        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;

        // 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);
    }
}

new MusicPlayer();
