/*****************************************************************************
* smsub Server Manager Subprocess
* Copyright (C) 2020 Syping
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* This software is provided as-is, no warranties are given to you, we are not
* responsible for anything with use of the software, you are self responsible.
*****************************************************************************/

#include <QCoreApplication>
#include <QTextStream>
#include "SMSubProcess.h"
#include "smsub.h"

SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory)
{
    process.setProgram(executable);
    process.setArguments(arguments);
    process.setWorkingDirectory(workingDirectory);
    process.setProcessChannelMode(QProcess::MergedChannels);

    QObject::connect(&process, SIGNAL(readyRead()), this, SLOT(readyRead()));
    QObject::connect(&process, SIGNAL(finished(int)), this, SLOT(processExit(int)));
    QObject::connect(&process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
}

void SMSubProcess::start()
{
    process.start(QIODevice::ReadWrite);
}

void SMSubProcess::readyRead()
{
    while (process.canReadLine()) {
        const QByteArray readData = process.readLine().trimmed();
        emit outputWritten(readData + '\n');
    }
}

void SMSubProcess::processExit(int exitCode)
{
    emit processStopped();
    QCoreApplication::exit(exitCode);
}

void SMSubProcess::processError(QProcess::ProcessError error)
{
    if (likely(error == QProcess::FailedToStart)) {
        QTextStream(stderr) << "Process failed to start!" << endl;
        QCoreApplication::exit(1);
    }
    else if (error == QProcess::UnknownError) {
        QTextStream(stderr) << "Unknown error occurred!" << endl;
        QCoreApplication::exit(1);
    }
}

void SMSubProcess::killProcess()
{
    process.kill();
}

void SMSubProcess::stopProcess()
{
    process.terminate();
}

void SMSubProcess::writeInput(const QByteArray &input)
{
    process.write(input);
}