import * as THREE from 'three';
import { state } from '../state.js';
import { turnTvScreenOff, turnTvScreenOn, showStandbyScreen } from '../scene/projection-screen.js';
import sceneFeatureManager from '../scene/SceneFeatureManager.js';
import { MediaStorage } from './media-storage.js';
import { showToast } from './ui-utils.js';

// Register a feature to handle party start
sceneFeatureManager.register({
    init: () => {},
    update: () => {},
    onPartyStart: () => {
        if (state.videoUrls && state.videoUrls.length > 0) {
            startVideoPlayback();
        }
    },
    onPartyEnd: () => {
        if (state.videoElement && !state.videoElement.paused) {
            state.videoElement.pause();
            updatePlayPauseButton();
        }
    }
});

// --- Play video by index ---
export function playVideoByIndex(index) {
    state.currentVideoIndex = index;
    const url = state.videoUrls[index];

    // Dispose of previous texture to free resources
    if (state.videoTexture) {
        state.videoTexture.dispose();
        state.videoTexture = null;
    }

    // Loop logic: if index is out of bounds, wrap around
    if (index >= state.videoUrls.length) {
        index = 0;
    }

    state.videoElement.src = url;
    state.videoElement.muted = true;
    state.videoElement.load();
    
    // Set loop property: only loop if it's the only video loaded
    state.videoElement.loop = false; //state.videoUrls.length === 1;

    // Auto-play next video when this one ends
    state.videoElement.onended = () => playNextVideo();

    
    state.videoElement.onloadeddata = () => {
        // 1. Create the Three.js texture
        state.videoTexture = new THREE.VideoTexture(state.videoElement);
        state.videoTexture.minFilter = THREE.LinearFilter;
        state.videoTexture.magFilter = THREE.LinearFilter;
        state.videoTexture.format = THREE.RGBAFormat; 
        state.videoTexture.needsUpdate = true;

        // 2. Apply the video texture to the screen mesh
        turnTvScreenOn();
        
        // 3. Start playback and trigger the warm-up effect simultaneously
        state.videoElement.play().then(() => {
            state.isVideoLoaded = true;
            // Use the defined base intensity for screen glow
            state.screenLight.intensity = state.originalScreenIntensity; 
            // Initial status message with tape count
            console.info(`Playing tape ${state.currentVideoIndex + 1} of ${state.videoUrls.length}.`);
            updatePlayPauseButton();
        }).catch(error => {
            state.screenLight.intensity = state.originalScreenIntensity * 0.5; // Dim the light if playback fails
            console.error(`Playback blocked for tape ${state.currentVideoIndex + 1}. Click Next Tape to try again.`);
            console.error('Playback Error: Could not start video playback.', error);
        });
    };
    
    state.videoElement.onerror = (e) => {
        state.screenLight.intensity = 0.1; // Keep minimum intensity for shadow map
        console.error(`Error loading tape ${state.currentVideoIndex + 1}.`);
        console.error('Video Load Error:', e);
    };
}

// --- Cycle to the next video ---
export function playNextVideo() {
    // Determine the next index, cycling back to 0 if we reach the end
    let nextIndex = (state.currentVideoIndex + 1) % state.videoUrls.length;
    state.baseTime += state.videoElement.duration;
    playVideoByIndex(nextIndex);
}

export function startVideoPlayback() {
    if (state.videoUrls && state.videoUrls.length > 0) {
        console.info(`Starting playback of ${state.videoUrls.length} tapes.`);
        if (state.loadTapeButton) state.loadTapeButton.classList.add("hidden");
        playVideoByIndex(0);
    }
}

export function playPreviousVideo() {
    let prevIndex = state.currentVideoIndex - 1;
    if (prevIndex < 0) {
        prevIndex = state.videoUrls.length - 1;
    }
    playVideoByIndex(prevIndex);
}

export function togglePlayPause() {
    if (!state.videoElement) return;
    
    if (state.videoElement.paused) {
        state.videoElement.play();
    } else {
        state.videoElement.pause();
    }
    updatePlayPauseButton();
}

function updatePlayPauseButton() {
    const btn = document.getElementById('video-play-pause-btn');
    if (btn) {
        btn.innerText = (state.videoElement && !state.videoElement.paused) ? 'Pause' : 'Play';
    }
}

export function initVideoUI() {
    // 1. File Input
    if (!state.fileInput) {
        const input = document.createElement('input');
        input.type = 'file';
        input.id = 'fileInput';
        input.multiple = true;
        input.accept = 'video/*';
        input.style.display = 'none';
        document.body.appendChild(input);
        state.fileInput = input;
    }
    state.fileInput.onchange = loadVideoFile;

    // 2. Load Button
    if (!state.loadTapeButton) {
        const btn = document.createElement('button');
        btn.id = 'loadTapeButton';
        btn.innerText = 'Load Tapes';
        Object.assign(btn.style, {
            position: 'absolute',
            top: '20px',
            left: '20px',
            zIndex: '1000',
            padding: '10px 20px',
            fontSize: '16px',
            cursor: 'pointer',
            background: '#fff',
            color: '#000',
            border: 'none',
            borderRadius: '5px',
            fontFamily: 'sans-serif'
        });
        document.body.appendChild(btn);
        state.loadTapeButton = btn;
    }
    state.loadTapeButton.onclick = () => state.fileInput.click();

    // Restore tapes from storage
    MediaStorage.getTapes().then(files => {
        if (files && files.length > 0) {
            processVideoFiles(files);
        }
    });
}

// --- Video Loading Logic (handles multiple files) ---
export function loadVideoFile(event) {
    const files = event.target.files;
    if (files.length === 0) {
        console.info('File selection cancelled.');
        return;
    }

    processVideoFiles(files);
    if (state.videoUrls.length > 0) {
        showToast(`Loaded ${state.videoUrls.length} tapes`, 'success');
    }
    MediaStorage.saveTapes(files);
}

function processVideoFiles(files) {
    // 1. Clear previous URLs and revoke object URLs to prevent memory leaks
    state.videoUrls.forEach(url => URL.revokeObjectURL(url));
    state.videoUrls = [];
    state.videoFilenames = [];

    // 2. Populate the new videoUrls array
    for (let i = 0; i < files.length; i++) {
        const file = files[i];
        if (file.type.startsWith('video/') && file.size > 0) {
            state.videoUrls.push(URL.createObjectURL(file));
            state.videoFilenames.push(file.name);
        }
    }

    if (state.videoUrls.length === 0) {
        console.info('No valid video files selected.');
        showToast('Error: No valid video files loaded.', 'error');
        return;
    }
    
    // Update Config UI
    const configUI = sceneFeatureManager.features.find(f => f.constructor.name === 'ConfigUI');
    if (configUI) configUI.updateStatus();

    // 3. Start playback logic
    console.info(`Loaded ${state.videoUrls.length} tapes.`);
    
    if (state.partyStarted) {
        startVideoPlayback();
    } else {
        console.info("Tapes loaded. Waiting for party start...");
        showStandbyScreen();
    }
}