"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable:no-console
const fs_1 = require("fs");
const glob = require("glob");
const path = require("path");
const pify = require("pify");
const __1 = require("..");
const BaseForLines_1 = require("../models/BaseForLines");
const recordCoverage_1 = require("../recordCoverage");
const sounds_1 = require("../sounds");
const terminal_1 = require("../ui/terminal");
function sleep(ms) {
    return __awaiter(this, void 0, void 0, function* () {
        return new Promise((resolve) => setTimeout(resolve, ms));
    });
}
function run() {
    return __awaiter(this, void 0, void 0, function* () {
        terminal_1.default.setSmallTerminal(true);
        const files = yield pify(glob)('./gists/*/script.txt');
        console.log(`Looping over ${files.length} games...`);
        console.log(`Screen size is ${process.stdout.columns} wide and ${process.stdout.rows} high`);
        for (const filename of files) {
            console.log(`Parsing and rendering ${filename}`);
            const gistId = path.basename(path.dirname(filename));
            const code = fs_1.readFileSync(filename, 'utf-8');
            let startTime = Date.now();
            const { data, validationMessages } = __1.Parser.parse(code);
            if (!data) {
                throw new Error(`BUG: gameData was not set yet`);
            }
            if (validationMessages) {
                validationMessages.forEach(({ source, level, message }) => {
                    const { lineNum, colNum } = BaseForLines_1.getLineAndColumn(source.code, source.sourceOffset);
                    console.warn(`(${lineNum}:${colNum}) ${level} : ${message}`);
                });
            }
            // Draw the "first" level (after the messages)
            let currentLevel = data.levels.filter((level) => level.isMap())[0];
            // have some default keypresses but load the most-recent partial if available
            let keypressesStr = [
                'WSSW',
                'ADDDA',
                'X',
                'SWWS',
                'DAAD'
            ].join('').split('').join('.');
            const recordingsPath = path.join(__dirname, `../../gist-solutions/${gistId}.json`);
            if (fs_1.existsSync(recordingsPath)) {
                const recordings = JSON.parse(fs_1.readFileSync(recordingsPath, 'utf-8')).solutions;
                // TODO: Use the following rules for finding which recording to play:
                // - find the last partially (or) completed Map
                // - pick the first Map
                if (recordings) {
                    recordings.forEach((recording, index) => {
                        if (recording && data.levels[index].isMap()) {
                            keypressesStr = recording.partial || recording.solution || '';
                            // Trim the keypresses down so the game does not take too long to run
                            keypressesStr = keypressesStr.substring(0, 150);
                            currentLevel = data.levels[index];
                        }
                    });
                }
                else {
                    currentLevel = data.levels.filter((l) => l.isMap())[0];
                }
            }
            if (currentLevel) {
                startTime = Date.now();
                const engine = new __1.GameEngine(data);
                const levelNum = data.levels.indexOf(currentLevel);
                engine.setLevel(levelNum);
                if (process.env.LOG_LEVEL === 'debug') {
                    console.error('');
                    console.error('');
                    console.error(`Start playing "${data.title}". Level ${levelNum}`);
                }
                console.log(`Loading Cells into the level took ${Date.now() - startTime}ms`);
                // engine.on('cell:updated', cell => {
                //   UI.drawCellAt(cell, cell.rowIndex, cell.colIndex, false)
                // })
                terminal_1.default.setGameEngine(engine);
                terminal_1.default.clearScreen();
                terminal_1.default.renderScreen(true);
                terminal_1.default.writeDebug(`"${data.title}"`, 0);
                startTime = Date.now();
                for (let i = 0; i < keypressesStr.length; i++) {
                    switch (keypressesStr[i]) {
                        case 'W':
                            engine.press(__1.RULE_DIRECTION.UP);
                            break;
                        case 'S':
                            engine.press(__1.RULE_DIRECTION.DOWN);
                            break;
                        case 'A':
                            engine.press(__1.RULE_DIRECTION.LEFT);
                            break;
                        case 'D':
                            engine.press(__1.RULE_DIRECTION.RIGHT);
                            break;
                        case 'X':
                            engine.press(__1.RULE_DIRECTION.ACTION);
                            break;
                        case '.':
                        case ',':
                            // just .tick()
                            break;
                        default:
                            throw new Error(`BUG: Invalid keypress character "${keypressesStr[i]}"`);
                    }
                    startTime = Date.now();
                    const { changedCells } = engine.tick();
                    // UI.renderScreen(data, engine.currentLevel)
                    // Draw any cells that moved
                    terminal_1.default.drawCells(changedCells, false);
                    const msg = `Tick ${i} of "${data.title}" (took ${Date.now() - startTime}ms)`;
                    terminal_1.default.writeDebug(msg.substring(0, 160), 0);
                    // if (soundToPlay) {
                    //     await soundToPlay.play()
                    // }
                    yield sleep(1);
                    // if (changedCells.size === 0) {
                    //     break
                    // }
                }
                const absPath = path.resolve(filename);
                const gistName = path.basename(path.dirname(filename));
                recordCoverage_1.saveCoverageFile(data, absPath, `gists-${gistName}`);
            }
        }
        sounds_1.closeSounds();
    });
}
run().catch((err) => { throw err; });
//# sourceMappingURL=runGames.js.map