"use strict";
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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationController = void 0;
const readline = __importStar(require("readline"));
const chalk_1 = __importDefault(require("chalk"));
const CommandController_1 = require("./CommandController");
const SystemPromptController_1 = require("./SystemPromptController");
const ConversationHistoryController_1 = require("./ConversationHistoryController");
const NLController_1 = require("./NLController");
const ApplicationView_1 = require("../views/ApplicationView");
const MultilineController_1 = require("./MultilineController");
const StateController_1 = require("./StateController");
const TokenController_1 = require("./TokenController");
const art_1 = require("../utils/art");
class ApplicationController {
    constructor(filePaths) {
        this.filePaths = filePaths;
        this.applicationView = new ApplicationView_1.ApplicationView();
        this.filePaths = filePaths;
        this.multilineController = new MultilineController_1.MultilineController();
        this.conversationHistoryController = new ConversationHistoryController_1.ConversationHistoryController();
        this.systemPromptController = new SystemPromptController_1.SystemPromptController();
        this.stateController = new StateController_1.StateController();
        this.tokenController = new TokenController_1.TokenController({
            systemPromptController: this.systemPromptController,
            conversationHistoryController: this.conversationHistoryController,
        });
        this.nlController = new NLController_1.NLController({
            filePaths: this.filePaths,
            conversationHistoryController: this.conversationHistoryController,
            systemPromptController: this.systemPromptController,
            tokenController: this.tokenController,
        });
        this.commandController = new CommandController_1.CommandController({
            conversationHistoryController: this.conversationHistoryController,
            systemPromptController: this.systemPromptController,
            stateController: this.stateController,
            tokenController: this.tokenController,
        });
    }
    run() {
        console.clear();
        this.applicationView.genericRender(art_1.art7);
        const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout,
        });
        // immediately set the prompt
        rl.setPrompt(this.defaultPrompt());
        rl.prompt();
        rl.on("line", (input) => __awaiter(this, void 0, void 0, function* () {
            try {
                yield this.multilineController.handleMultilineInput(rl, input);
                if (this.multilineController.mode) {
                    rl.setPrompt(this.multilinePrompt());
                    return; // returning nothing prevents rotation
                }
                input = processInput(input);
                if (input === "") {
                    return rl.prompt();
                }
                else if (input[0] === "/") {
                    yield this.commandController.handleCommand(input);
                }
                else {
                    if (input === this.multilineController.delimiter) {
                        input = this.multilineController.returnBufferAndReset();
                    }
                    yield this.nlController.handleNL(input, () => {
                        rl.prompt();
                    });
                }
                rl.setPrompt(this.defaultPrompt());
                return rl.prompt();
            }
            catch (error) {
                console.error("Error occured:", error);
                return rl.prompt();
            }
        }));
        rl.on("close", () => __awaiter(this, void 0, void 0, function* () {
            yield this.exitHook();
        }));
    }
    /**
     * Saves the state of the application before exiting
     */
    exitHook() {
        return __awaiter(this, void 0, void 0, function* () {
            process.stdout.write("\n");
            const currName = this.stateController.getSaveName();
            if (currName) {
                // save state
                yield this.stateController.saveStateInterface({
                    saveName: this.stateController.getSaveName(),
                    overwrite: true,
                    conversationHistory: yield this.conversationHistoryController.getConversationHistory(),
                    trackedFiles: yield this.systemPromptController.getFilePaths(),
                    limit: this.tokenController.getConversationLimit(),
                });
            }
            else {
                this.applicationView.headerRender("State unavailable, current save discarded");
            }
            this.applicationView.headerRender("Exiting the program");
            process.exit(0);
        });
    }
    defaultPrompt() {
        const name = this.stateController.getSaveName();
        const bracketedName = chalk_1.default.gray(`(${name})`);
        const promptStr = chalk_1.default.gray `${this.stateController.getSaveName() ? `${bracketedName}` : "##"}`;
        // const promptStr = `${name}> `;
        return promptStr + (name ? chalk_1.default.white : chalk_1.default.gray) `> `;
    }
    multilinePrompt() {
        return "";
    }
}
exports.ApplicationController = ApplicationController;
// util functions
// TODO: consider moving this to a separate file
const processInput = (input) => {
    return input.trim();
};
