/**
 * Game Loop Module for AI Interactive Fiction
 * Manages the main game logic and connects various modules
 */
import { BaseModule } from './base-module.js';

class GameLoopModule extends BaseModule {
    constructor() {
        super('game-loop', 'Game Loop');
        
        // Dependencies
        this.dependencies = ['ui-controller', 'socket-client', 'text-buffer', 'sentence-queue', 'playback-coordinator', 'animation-queue', 'audio-manager', 'tts-factory', 'ui-input-handler', 'story-history'];
        
        // Game state
        this.gameState = {
            started: false,
            startedOnce: false,
            ended: false,
            canLoad: false,
            currentRoom: null,
            inventory: [],
            commandHistory: []
        };
        
        this.isRunning = false;
        
        // Bind methods using parent's bindMethods utility
        this.bindMethods([
            'start',
            'setupUiEventListeners',
            'setupSocketEventListeners',
            'updateGameState',
            'updateUIState',
            'refreshGameApiState',
            'hasSaveGame',
            'queueUnrenderedHistoryBlocks',
            'requestStartGame',
            'requestSaveGame',
            'requestLoadGame',
            'resetClientPlaybackAndDisplay'
        ]);
    }
    
    async initialize() {
        this.reportProgress(100, "Game loop initialized");
        return true;
    }
    
    start() {
        console.log("GameLoop: Starting game sequence...");
        
        try {
            // The dependencies are now automatically available via getModule
            this.updateUIState();
            this.setupUiEventListeners();
            
            console.log("GameLoop: Setting up socket listeners and connecting...");
            
            // Set up socket event listeners and connect
            this.setupSocketEventListeners();
            
            // Set the game loop as running
            this.isRunning = true;
        } catch (error) {
            console.error("Error starting game loop:", error);
        }
    }

    setupUiEventListeners() {
        if (this.uiEventsBound) return;
        this.uiEventsBound = true;

        document.addEventListener('ui:game:restart', () => this.requestStartGame());
        document.addEventListener('ui:game:save', () => this.requestSaveGame());
        document.addEventListener('ui:game:load', () => this.requestLoadGame());
        document.addEventListener('story:input-mode', (event) => {
            if (event.detail !== 'end') {
                return;
            }
            this.gameState.started = false;
            this.gameState.ended = true;
            this.gameState.canSave = false;
            this.updateUIState();
        });
    }
    
    setupSocketEventListeners() {
        // Get the socket client module using parent's getModule method
        const socketClient = this.getModule('socket-client');
        
        if (!socketClient) {
            console.error("Socket client module not found");
            return;
        }
        
        // Connect UI controller to socket client for command handling
        const uiController = this.getModule('ui-controller');
        
        if (uiController) {
            uiController.socketClient = socketClient;
        } else {
            console.warn("GameLoop: UI Controller not ready for Socket Client assignment.");
        }
        
        // Listen for socket connection event
        socketClient.on('connect', () => {
            console.log("GameLoop: Socket connected event received.");
            
            this.refreshGameApiState();
        });
        
        // Listen for game state updates
        socketClient.on('gameStateUpdate', (data) => {
            console.log("GameLoop: Game state update received", data);
            this.updateGameState(data);
        });
        
        // Listen for narrative responses
        socketClient.on('narrativeResponse', (data) => {
            console.log("GameLoop: Narrative response received", data);
            // Text processing is handled by socket-client -> text-buffer -> ui-controller pipeline
        });
        
        socketClient.on('gameSaved', () => {
            this.gameState.canLoad = true;
            this.updateUIState();
        });

        socketClient.on('gameLoaded', () => {
            this.gameState.started = true;
            this.gameState.canSave = true;
            this.gameState.canLoad = true;
            this.updateUIState();
        });
        
        // Connect to the socket server
        socketClient.connect().then(success => {
            if (success) {
                console.log("GameLoop: Socket connection established successfully.");
            } else {
                console.error("GameLoop: Failed to connect to socket server");
            }
        });
    }

    async refreshGameApiState() {
        const socketClient = this.getModule('socket-client');
        if (!socketClient || !socketClient.getConnectionStatus()) return;

        const [running, hasSave] = await Promise.all([
            socketClient.isGameRunning(),
            this.hasSaveGame(1)
        ]);

        this.gameState.started = Boolean(running?.result);
        if (this.gameState.started) {
            this.gameState.startedOnce = true;
            this.gameState.ended = false;
        }
        this.gameState.canSave = this.gameState.started;
        this.gameState.canLoad = Boolean(hasSave?.result);
        this.updateUIState();
    }
    
    /**
     * Update the game state
     * @param {Object} data - New game state data
     */
    updateGameState(data) {
        if (!data) return;
        
        // Update game state
        if (data.currentRoom) {
            this.gameState.currentRoom = data.currentRoom;
        }
        
        if (data.inventory) {
            this.gameState.inventory = data.inventory;
        }
        
        // Update UI with new game state
        this.updateUIState();
    }
    
    /**
     * Update UI with current game state
     */
    updateUIState() {
        const uiController = this.getModule('ui-controller');
        if (!uiController) return;
        
        // Update UI components based on game state
        const state = {
            canRestart: true,
            canSave: Boolean(this.gameState.canSave && this.gameState.started),
            canLoad: Boolean(this.gameState.canLoad),
            gameStarted: Boolean(this.gameState.started || this.gameState.startedOnce || this.gameState.ended)
        };
        document.body.dataset.gameRunning = state.gameStarted ? 'true' : 'false';
        uiController.updateButtonStates(state);
    }
    
    /**
     * Request to start a new game
     */
    async requestStartGame() {
        const socketClient = this.getModule('socket-client');
        if (!socketClient) return;

        this.gameState.started = true;
        this.gameState.startedOnce = true;
        this.gameState.ended = false;
        this.gameState.canSave = true;
        this.updateUIState();
        await this.resetClientPlaybackAndDisplay();
        const storyHistory = this.getModule('story-history');
        if (storyHistory && typeof storyHistory.startNewGame === 'function') {
            await storyHistory.startNewGame();
        }
        const response = await socketClient.newGame();
        if (!response?.success) {
            console.error('GameLoop: newGame failed', response);
            this.gameState.started = false;
            this.gameState.canSave = false;
            this.updateUIState();
            return;
        }
        this.gameState.started = true;
        this.gameState.startedOnce = true;
        this.gameState.ended = false;
        this.gameState.canSave = true;
        this.gameState.canLoad = Boolean(response.canLoad);
        this.updateUIState();
    }
    
    /**
     * Request to save the current game
     */
    async requestSaveGame() {
        const socketClient = this.getModule('socket-client');
        if (!socketClient || !this.gameState.started) return;

        const response = await socketClient.saveGame(1);
        if (response?.success) {
            const storyHistory = this.getModule('story-history');
            const audioManager = this.getModule('audio-manager');
            if (storyHistory && typeof storyHistory.saveSlot === 'function') {
                await storyHistory.saveSlot(1, {
                    inkState: response.savedState || null,
                    latestRenderedBlockId: storyHistory.latestRenderedBlockId || 0,
                    renderedLineCount: storyHistory.renderedLineCount || 0,
                    musicState: audioManager?.getMusicState?.() || null
                });
            }
            this.gameState.canLoad = true;
            this.updateUIState();
        }
    }
    
    /**
     * Request to load a saved game
     */
    async requestLoadGame() {
        const socketClient = this.getModule('socket-client');
        if (!socketClient) return;

        const storyHistory = this.getModule('story-history');
        const browserSave = storyHistory && typeof storyHistory.loadSlot === 'function'
            ? await storyHistory.loadSlot(1)
            : null;
        const hasSave = browserSave ? { result: true } : await socketClient.hasSaveGame(1);
        if (!hasSave?.result) {
            this.gameState.canLoad = false;
            this.updateUIState();
            return;
        }

        this.gameState.started = true;
        this.gameState.startedOnce = true;
        this.gameState.ended = false;
        this.gameState.canSave = true;
        this.gameState.canLoad = true;
        this.updateUIState();
        await this.resetClientPlaybackAndDisplay();
        document.dispatchEvent(new CustomEvent('story:history-restoring', {
            detail: { active: true, reason: 'load-game' }
        }));
        if (browserSave?.gameId && storyHistory?.setCurrentGame) {
            storyHistory.setCurrentGame(
                browserSave.gameId,
                browserSave.latestBlockId || 0,
                browserSave.latestRenderedBlockId || 0,
                browserSave.renderedLineCount || 0
            );
        }
        const uiController = this.getModule('ui-controller');
        if (browserSave && uiController?.displayHandler?.restoreFromHistory) {
            await uiController.displayHandler.restoreFromHistory(browserSave);
        }
        const audioManager = this.getModule('audio-manager');
        if (browserSave?.musicState && audioManager?.restoreMusicState) {
            await audioManager.restoreMusicState(browserSave.musicState);
        }
        const hasUnrenderedHistory = browserSave &&
            Number(browserSave.latestBlockId || 0) > Number(browserSave.latestRenderedBlockId || 0);
        if (hasUnrenderedHistory) {
            const sentenceQueue = this.getModule('sentence-queue');
            sentenceQueue?.pauseBeforeNext?.('load-resume');
            document.dispatchEvent(new CustomEvent('story:process-state', {
                detail: { state: 'waiting-generating', reason: 'restoring-pending-output' }
            }));
        }
        const response = await socketClient.loadGame(1, browserSave?.inkState || null);
        if (response?.success && hasUnrenderedHistory) {
            await this.queueUnrenderedHistoryBlocks(browserSave);
        }
        if (response?.success) {
            this.gameState.started = true;
            this.gameState.startedOnce = true;
            this.gameState.ended = false;
            this.gameState.canSave = true;
            this.gameState.canLoad = true;
            this.updateUIState();
        }
        if (!hasUnrenderedHistory) {
            document.dispatchEvent(new CustomEvent('story:history-restoring', {
                detail: { active: false, reason: 'load-game-complete' }
            }));
        } else {
            const clearRestoring = () => {
                document.dispatchEvent(new CustomEvent('story:history-restoring', {
                    detail: { active: false, reason: 'pending-output-drained' }
                }));
                document.removeEventListener('tts:queue-empty', clearRestoring);
            };
            document.addEventListener('tts:queue-empty', clearRestoring);
        }
    }

    async hasSaveGame(slot = 1) {
        const storyHistory = this.getModule('story-history');
        if (storyHistory && typeof storyHistory.hasSaveSlot === 'function') {
            const hasBrowserSave = await storyHistory.hasSaveSlot(slot);
            if (hasBrowserSave) return { success: true, result: true, slot };
        }
        const socketClient = this.getModule('socket-client');
        return socketClient?.hasSaveGame ? socketClient.hasSaveGame(slot) : { success: false, result: false };
    }

    async queueUnrenderedHistoryBlocks(saveRecord = {}) {
        const storyHistory = this.getModule('story-history');
        const textBuffer = this.getModule('text-buffer');
        if (!storyHistory || !textBuffer || typeof textBuffer.addBlocks !== 'function') return;
        const start = Math.max(1, Number(saveRecord.latestRenderedBlockId || 0) + 1);
        const end = Math.max(0, Number(saveRecord.latestBlockId || 0));
        if (end < start) return;
        const blocks = await storyHistory.getBlocksRange(saveRecord.gameId, start, end);
        textBuffer.addBlocks(blocks);
    }

    async resetClientPlaybackAndDisplay() {
        const playbackCoordinator = this.getModule('playback-coordinator');
        if (playbackCoordinator && typeof playbackCoordinator.stop === 'function') {
            await playbackCoordinator.stop();
        }

        const animationQueue = this.getModule('animation-queue');
        if (animationQueue && typeof animationQueue.clearAll === 'function') {
            animationQueue.clearAll();
        }

        const ttsFactory = this.getModule('tts-factory');
        if (ttsFactory && typeof ttsFactory.stop === 'function') {
            ttsFactory.stop();
        }

        const audioManager = this.getModule('audio-manager');
        if (audioManager && typeof audioManager.stopAllSounds === 'function') {
            audioManager.stopAllSounds();
        }

        const sentenceQueue = this.getModule('sentence-queue');
        if (sentenceQueue && typeof sentenceQueue.clear === 'function') {
            sentenceQueue.clear();
        }

        const textBuffer = this.getModule('text-buffer');
        if (textBuffer && typeof textBuffer.clear === 'function') {
            textBuffer.clear();
        }

        const uiController = this.getModule('ui-controller');
        if (uiController) {
            uiController.clearDisplay();
        }

        const inputHandler = this.getModule('ui-input-handler');
        if (inputHandler && typeof inputHandler.clearHistory === 'function') {
            inputHandler.clearHistory();
        }
    }
    
}

// Create the singleton instance
const GameLoop = new GameLoopModule();

// Export the module
export { GameLoop };
