"use strict";
/**
 * Command-line interface for running the interactive fiction game
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.GameRunner = void 0;
const readline = __importStar(require("readline"));
const path = __importStar(require("path"));
const dotenv = __importStar(require("dotenv"));
const game_engine_1 = require("../engine/game-engine");
const openrouter_provider_1 = require("../llm/openrouter-provider");
// Load environment variables
dotenv.config();
class GameRunner {
    constructor() {
        this.rl = null;
        this.gameContext = '';
        this.gameHistory = [];
        this.suggestedCommands = [];
        this.engine = new game_engine_1.TextAdventureEngine();
        this.llmProvider = new openrouter_provider_1.OpenRouterProvider();
    }
    /**
     * Initialize the game
     */
    async initialize(worldPath) {
        console.log('Initializing game...');
        // Initialize LLM provider
        const apiKey = process.env.OPENROUTER_API_KEY;
        const model = process.env.OPENROUTER_MODEL;
        if (!apiKey || !model) {
            throw new Error('Missing required environment variables: OPENROUTER_API_KEY and/or OPENROUTER_MODEL');
        }
        await this.llmProvider.initialize({
            apiKey,
            model,
            temperature: 0.7,
            maxTokens: 800
        });
        // Load the world
        const resolvedPath = path.resolve(worldPath);
        console.log(`Loading world from ${resolvedPath}...`);
        await this.engine.loadWorld(resolvedPath);
        console.log('Game initialized successfully!');
    }
    /**
     * Start the game in CLI mode
     */
    async start() {
        // Create readline interface for CLI mode
        this.rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });
        try {
            // Display introduction
            const introText = await this.engine.start();
            console.log('\n' + introText + '\n');
            // Look at initial room
            const initialLook = this.engine.processAction({ action: 'look', confidence: 1 });
            // Generate narrative description
            const narrativeRequest = {
                action: 'look',
                result: initialLook.message,
                roomDescription: this.engine.getCurrentRoomDescription(),
                visibleObjects: this.engine.getVisibleObjects(),
                visibleCharacters: this.engine.getVisibleCharacters(),
                tone: 'descriptive'
            };
            const narrative = await this.llmProvider.generateNarrative(narrativeRequest);
            console.log('\n' + narrative.text + '\n');
            // Store suggestions if available
            if (narrative.suggestions && narrative.suggestions.length > 0) {
                this.suggestedCommands = narrative.suggestions;
            }
            // Update game context
            this.updateGameContext(narrative.text);
            // Start the game loop
            this.gameLoop();
        }
        catch (error) {
            console.error('Error starting game:', error);
            this.end();
        }
    }
    /**
     * The main game loop for CLI mode
     */
    gameLoop() {
        if (!this.rl)
            return;
        this.rl.question('> ', async (input) => {
            if (input.toLowerCase() === 'quit' || input.toLowerCase() === 'exit') {
                this.end();
                return;
            }
            const response = await this.processCommand(input);
            console.log('\n' + response + '\n');
            // Continue the game loop
            this.gameLoop();
        });
    }
    /**
     * Process a player command and return the narrative response
     * Used by both CLI and web interfaces
     */
    async processCommand(input) {
        try {
            // Process player input
            const actionRequest = {
                playerInput: input,
                currentRoom: this.engine.getWorldModel().rooms[this.engine.getCurrentState().currentRoomId].name,
                visibleObjects: this.engine.getVisibleObjects().map(id => this.engine.getWorldModel().objects[id].name),
                visibleCharacters: this.engine.getVisibleCharacters().map(id => this.engine.getWorldModel().characters[id].name),
                possibleActions: this.engine.getAvailableActions(),
                inventory: this.engine.getCurrentState().inventory.map(id => this.engine.getWorldModel().objects[id].name),
                gameContext: this.gameContext
            };
            if (this.rl) {
                console.log('Thinking...');
            }
            // Translate player input to action
            const action = await this.llmProvider.translateAction(actionRequest);
            // Process the action in the game engine
            const actionResult = this.engine.processAction(action);
            // If state changed, update it
            if (actionResult.stateChanged && actionResult.newState) {
                this.engine.getCurrentState().currentRoomId = actionResult.newState.currentRoomId;
                this.engine.getCurrentState().inventory = actionResult.newState.inventory;
                this.engine.getCurrentState().visitedRooms = actionResult.newState.visitedRooms;
                this.engine.getCurrentState().flags = actionResult.newState.flags;
                this.engine.getCurrentState().counters = actionResult.newState.counters;
            }
            // Generate narrative description
            const narrativeRequest = {
                action: `${action.action}${action.object ? ' ' + action.object : ''}${action.target ? ' on ' + action.target : ''}`,
                result: actionResult.message,
                roomDescription: this.engine.getCurrentRoomDescription(),
                visibleObjects: this.engine.getVisibleObjects().map(id => this.engine.getWorldModel().objects[id].name),
                visibleCharacters: this.engine.getVisibleCharacters().map(id => this.engine.getWorldModel().characters[id].name),
                previousContext: this.gameHistory.slice(-3).join('\n'),
                tone: 'descriptive'
            };
            const narrative = await this.llmProvider.generateNarrative(narrativeRequest);
            // Store suggestions if available
            if (narrative.suggestions && narrative.suggestions.length > 0) {
                this.suggestedCommands = narrative.suggestions;
            }
            // Update game context with the new narrative
            this.updateGameContext(narrative.text);
            // Return the narrative text
            return narrative.text;
        }
        catch (error) {
            console.error('Error processing input:', error);
            return 'Something went wrong. Please try again.';
        }
    }
    /**
     * End the game
     */
    end() {
        console.log('\nThanks for playing!');
        if (this.rl) {
            this.rl.close();
            this.rl = null;
        }
        this.engine.end();
        if (process.env.NODE_ENV !== 'production') {
            process.exit(0);
        }
    }
    /**
     * Update the game context with new narrative
     */
    updateGameContext(narrative) {
        // Add to history
        this.gameHistory.push(narrative);
        // Keep history limited to last 10 entries
        if (this.gameHistory.length > 10) {
            this.gameHistory.shift();
        }
        // Update current context (last 5 entries)
        this.gameContext = this.gameHistory.slice(-5).join('\n');
    }
    /**
     * Get the current game state
     * Used by web interface
     */
    getGameState() {
        return {
            world: this.engine.getWorldModel(),
            currentRoomId: this.engine.getCurrentState().currentRoomId,
            inventory: this.engine.getCurrentState().inventory,
            visitedRooms: this.engine.getCurrentState().visitedRooms,
            flags: this.engine.getCurrentState().flags,
            counters: this.engine.getCurrentState().counters
        };
    }
    /**
     * Get the current room description
     * Used by web interface
     */
    getCurrentRoomDescription() {
        const roomId = this.engine.getCurrentState().currentRoomId;
        return this.engine.getWorldModel().rooms[roomId].description;
    }
    /**
     * Get suggested actions for the current game state
     * Used by web interface
     */
    getSuggestions() {
        return this.suggestedCommands;
    }
    /**
     * Load a saved game state
     * Used by web interface
     */
    loadGameState(savedState) {
        // Set the current state to match the saved state
        this.engine.getCurrentState().currentRoomId = savedState.currentRoomId;
        this.engine.getCurrentState().inventory = savedState.inventory;
        this.engine.getCurrentState().visitedRooms = savedState.visitedRooms;
        this.engine.getCurrentState().flags = savedState.flags;
        this.engine.getCurrentState().counters = savedState.counters;
    }
}
exports.GameRunner = GameRunner;
//# sourceMappingURL=game-runner.js.map