#include "cmd.hpp"

/* The facility to run jobs on command. Uses a spell book mental model.
 * Needs to allow for long running jobs, ie runtime VM, LSP server, etc
 */


CommandRunner::CommandRunner() : QObject() {
    timer = new QTimer();
    timer->setInterval(BUFFER_TIME);
    connect(timer, &QTimer::timeout, this, &CommandRunner::readBuffers);

    process = new QProcess();
    process->setProcessChannelMode(QProcess::MergedChannels);
    // see docs for QProcess::finished. Not sure what's happening here.
    connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), 
            this, &CommandRunner::processFinished);
    connect(process, &QProcess::errorOccurred, this, &CommandRunner::handleError);
}

QString CommandRunner::read() {
    return process->readAll();
}

void CommandRunner::readBuffers() {
    QString result = read();
    if (!result.isEmpty()) {
        emit resultsReady(result);
    }
}

void CommandRunner::handleError(QProcess::ProcessError error) {
    closeOut();
}

void CommandRunner::processFinished(int code, QProcess::ExitStatus status) {
    closeOut();
}

void CommandRunner::closeOut() {
    readBuffers();
    process->close();
    timer->stop();
    emit finished();
}

void CommandRunner::start(QStringList args) {
    if (process->state() == QProcess::NotRunning) {
        if (args.length() > 1) {
            process->start(args[0], args.mid(1));
        } else {
            process->start(args[0], QStringList());
        }
        timer->start();
    } else {
        // TODO: implement stack
    }
}

void CommandRunner::stopThread() {
    process->close();
    process->waitForFinished();
}
