"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LinterPlugin = void 0;
const config_1 = require("../config");
const PluginBase_1 = require("./PluginBase");
const child_process_1 = require("child_process");
class LinterPlugin extends PluginBase_1.PluginBase {
    static meta = {
        key: "linter",
        name: "Linter Plugin",
        requires: [],
    };
    meta = LinterPlugin.meta;
    eventService;
    runState = new Map();
    runTimes = new Map();
    constructor(context) {
        super(context);
        this.eventService = context.Events;
        this.context.Events.on("file:post-edit", this.handleFilePostEdit.bind(this));
    }
    async embed() {
        return [];
    }
    async call(userPrompt) {
        return "";
    }
    async handleFilePostEdit(payload) {
        const { filePath } = payload;
        await this.enqueueLint(filePath);
    }
    async enqueueLint(filePath) {
        const config = await (0, config_1.getConfig)();
        const extension = filePath.split(".").pop();
        if (!extension || !config.lintCommands || !config.lintCommands[extension]) {
            return;
        }
        let lintCommand = config.lintCommands[extension];
        if (lintCommand.includes("$1")) {
            lintCommand = lintCommand.replace("$1", filePath);
        }
        const job = { filePath, extension, command: lintCommand };
        const state = this.runState.get(extension);
        if (!state || !state.current) {
            this.runState.set(extension, { current: job, next: null });
            this.runLint(job);
        }
        else {
            this.runState.set(extension, { current: state.current, next: job });
        }
    }
    getEstimatedTime(extension) {
        const times = this.runTimes.get(extension);
        if (!times || times.length === 0)
            return null;
        return Math.round(times.reduce((a, b) => a + b, 0) / times.length);
    }
    recordRunTime(extension, durationMs) {
        if (!this.runTimes.has(extension)) {
            this.runTimes.set(extension, []);
        }
        const times = this.runTimes.get(extension);
        times.push(durationMs);
        if (times.length > 5) {
            times.shift();
        }
    }
    runLint(job) {
        const { extension, command, filePath } = job;
        const startTime = Date.now();
        this.eventService.emit("linter:started", { extension, filePath, command });
        const estimatedMs = this.getEstimatedTime(extension);
        const estimatedMsg = estimatedMs
            ? ` Expected completion time: ~${Math.round(estimatedMs / 1000)}s.`
            : "";
        this.eventService.emit("agent:msg", `<Workflow>
LinterPlugin: Running lint command for .${extension} files in the background.${estimatedMsg}
Command: ${command}
You will receive the results shortly. Continue working and the linter output will be provided when ready.
</Workflow>`);
        let stdout = "";
        let stderr = "";
        const child = (0, child_process_1.spawn)(command, { shell: true });
        child.stdout?.on("data", (d) => {
            stdout += d.toString();
        });
        child.stderr?.on("data", (d) => {
            stderr += d.toString();
        });
        child.once("error", (err) => {
            const durationMs = Date.now() - startTime;
            this.recordRunTime(extension, durationMs);
            this.onLintFinished(job, false, `Failed to start lint command: ${err.message}`, durationMs);
        });
        child.once("exit", (code) => {
            const durationMs = Date.now() - startTime;
            this.recordRunTime(extension, durationMs);
            const hasErrors = stderr.trim().length > 0;
            this.onLintFinished(job, !hasErrors, hasErrors ? stderr : stdout, durationMs);
        });
    }
    onLintFinished(job, success, output, durationMs) {
        const { extension, filePath, command } = job;
        this.eventService.emit("linter:finished", {
            extension,
            filePath,
            command,
            success,
            output,
            durationMs,
        });
        if (!success) {
            this.eventService.emit("agent:msg", `<Workflow>
LinterPlugin: Lint finished with errors for .${extension} files (took ${Math.round(durationMs / 1000)}s).
${output}
Please review and fix the issues above.
</Workflow>`);
        }
        const state = this.runState.get(extension);
        if (state?.next) {
            const nextJob = state.next;
            this.runState.set(extension, { current: nextJob, next: null });
            this.runLint(nextJob);
        }
        else {
            this.runState.set(extension, { current: null, next: null });
        }
    }
}
exports.LinterPlugin = LinterPlugin;
//# sourceMappingURL=LinterPlugin.js.map