#include "kernelinstaller.h"
#include "ui_kernelinstaller.h"

#include <ctime>
#include <cstdlib>
#include <QFile>
#include <unistd.h>
#include <QDebug>

#define MAX_TMP_NUM 1024
#define MIN_TMP_NUM 0

KernelInstaller::KernelInstaller(Option option, QStringList kernelList, QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::KernelInstaller)
{
    ui->setupUi(this);
    runOption = option;
    // 修改提示文本
    QString kernel = "";
    foreach (QString name, kernelList) {
        kernel += name + " ";
    }

    switch(runOption) {
    case Option::Install:
        ui->m_status->setText(tr("Try to install ") + kernel);
        break;
    case Option::Remove:
        ui->m_status->setText(tr("Try to remove ") + kernel);
        break;
    case Option::Reconfigure:
        ui->m_status->setText(tr("Try to reconfigure ") + kernel);
        break;
    case Option::Update:
        ui->m_status->setText(tr("Try to update apt cache"));
        break;
    case Option::Upgrade:
        ui->m_status->setText(tr("Try to upgrade ") + kernel);
        break;
    }


    this->kernelList = kernelList;
    terminal = new QTermWidget(0);
    terminal->setColorScheme("DarkPastels");
    terminal->setAutoClose(false);
    ui->verticalLayout->addWidget(terminal);
    StartInstaller();
}

void KernelInstaller::StartInstaller()
{
    // 随机生成目录
    srand(time(0));
    int randomNumber = (rand() % (MAX_TMP_NUM - MIN_TMP_NUM)) + 1;  // 左闭右闭
    QString tempPath = tempDir + "/gxde-kernel-manager-installer-" + QString::number(randomNumber) + ".sh";
    QString tempLoaderPath = tempDir + "/gxde-kernel-manager-root-loader-installer-" + QString::number(randomNumber) + ".sh";
    QFile file(tempPath);
    file.open(QFile::WriteOnly);
    file.write(BuildKernelInstallerBash(this->kernelList, tempPath).toUtf8());
    file.close();
    QFile loaderFile(tempLoaderPath);
    loaderFile.open(QFile::WriteOnly);
    loaderFile.write(BuildKernelRootLoaderInstallerBash(tempPath, tempLoaderPath).toUtf8());
    loaderFile.close();
    terminal->setShellProgram("/usr/bin/bash");
    terminal->setArgs(QStringList() << tempLoaderPath);
    terminal->startShellProgram();
    processID = terminal->getShellPID();
    // 使用 QTimer 用于判断内核是否安装完成
    runStatusTimer = new QTimer();
    runStatusTimer->setInterval(100);
    connect(runStatusTimer, &QTimer::timeout, this, &KernelInstaller::CheckInstallerStatusTimer);
    runStatusTimer->start();
}

QString KernelInstaller::BuildKernelInstallerBash(QStringList kernelList, QString tempFilePath) const
{
    // 转换数据
    QString kernel = "";
    foreach (QString name, kernelList) {
        kernel += name + " ";
    }
    QString filePath = ":/shell/kernel-installer-template.sh";
    switch(runOption) {
    case Option::Install:
        filePath = ":/shell/kernel-installer-template.sh";
        break;
    case Option::Remove:
        filePath = ":/shell/kernel-installer-remove-template.sh";
        break;
    case Option::Reconfigure:
        filePath = ":/shell/kernel-installer-reconfigure-template.sh";
        break;
    case Option::Update:
        filePath = ":/shell/kernel-installer-update-template.sh";
        break;
    case Option::Upgrade:
        filePath = ":/shell/kernel-installer-upgrade-template.sh";
        break;
    }

    QFile file(filePath);
    file.open(QFile::ReadOnly);
    QString data = file.readAll();
    data = data.replace("${KernelList}", kernel);
    data = data.replace("${kernelInstallerShellTempPath}", tempFilePath);
    file.close();
    return data;
}

QString KernelInstaller::BuildKernelRootLoaderInstallerBash(QString tempFilePath, QString tempLoaderFilePath) const
{
    QFile file(":/shell/kernel-installer-root-loader-template.sh");
    file.open(QFile::ReadOnly);
    QString data = file.readAll();
    data = data.replace("${kernelInstallerShellTempPath}", tempFilePath);
    data = data.replace("${kernelInstallerRootLoaderShellTempPath}", tempLoaderFilePath);
    file.close();
    return data;
}

/*
 * -1 为进程正在运行(正常)
 * -2 为无法读取进程信息(异常)
*/
int KernelInstaller::CheckInstallerStatus()
{
    if(QFile::exists("/proc/" + QString::number(processID))) {
        // 如果进程存在
        return -1;
    }
    QFile file("/tmp/gxde-kernel-manager-installer-status");
    if(!file.exists()) {
        return -2;
    }
    file.open(QFile::ReadOnly);
    QString data = file.readAll();
    file.close();
    data = data.replace("\n", "").replace(" ", "");
    return data.toInt();
}

void KernelInstaller::CheckInstallerStatusTimer()
{
    int status = CheckInstallerStatus();
    if(status == -1) {
        return;
    }
    // 关闭 Timer 防止一直发送错误的信号
    runStatusTimer->stop();
    emit InstallFinished(status);
    // 安装完成
    if(status == 0) {
        ui->m_status->setText(tr("Done"));
        ui->m_icon->setText("<img src=':/icon/dialog-ok.svg'>");
        return;
    }
    ui->m_icon->setText("<img src=':/icon/dialog-error.svg'>");
    ui->m_status->setText(tr("Something error, exit code: ") + QString::number(status));
}

KernelInstaller::~KernelInstaller()
{
    delete ui;
}