/*
 * Copyright 2022 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with thi1s program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "processinfo.h"
#include "dbusservices/applauncher.h"

ProcessInfo::ProcessInfo(qint64 pid, QList<qint64> childrenPid, AppStatus status, QList<WindowId> wids, QStringList args)
{
    initProcessInfo(pid, childrenPid, status, wids, args);
}

qint64 ProcessInfo::getPid() const
{
    return pid;
}

void ProcessInfo::setPid(const qint64 &appPid)
{
    pid = appPid;
}

ProcessInfo::AppStatus ProcessInfo::getStatus() const
{
    return status;
}

void ProcessInfo::setStatus(const AppStatus &appStatus)
{
    status = appStatus;
}

QList<WindowId> ProcessInfo::getWids() const
{
    return wids;
}

void ProcessInfo::setWids(const QList<WindowId> &appWids)
{
    qDebug() << "setWids" << appWids.count();
    wids = appWids;
}

void ProcessInfo::pushWids(const WindowId &wid)
{
    qDebug() << __FUNCTION__ << wid;
    if (wids.isEmpty()) {
        qDebug() << "---wids.isEmpty()--- push";
        wids << wid;
        return;
    }
    for (auto &widInfo : wids) {
        qDebug() << "---wids---" << widInfo;
        if (widInfo == wid) {
            return;
        }
        wids << wid;
        qDebug() << __FUNCTION__ << "push" << wid;
    }
}

void ProcessInfo::removeWids(const WindowId &wid)
{
    qDebug() << __FUNCTION__ << wid;
    for (auto &widInfo : wids) {
        if (widInfo == wid) {
            qDebug() << __FUNCTION__ << "remove" << wid;
            wids.removeOne(wid);
        }
    }
}

QStringList ProcessInfo::getArgs() const
{
    return args;
}

void ProcessInfo::setArgs(const QStringList &appArgs)
{
    args = appArgs;
}

QList<qint64> ProcessInfo::getTasks() const
{
    return tasks;
}

void ProcessInfo::setTasks(const qint64 &appPid)
{
    qDebug() << __FUNCTION__ << appPid;
    QString tasksFilePath = "/proc/" + QString::number(appPid) + "/task";

    QDir dir(tasksFilePath);

    //取到所有的文件和文件名，但是去掉.和..的文件夹
    dir.setFilter(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot);
    if (!dir.exists()) {
        qWarning() << "exists";
        return;
    }

    QFileInfoList list = dir.entryInfoList();
    if(list.size() < 1 ) {
        qWarning() << "error";
        return;
    }

    QStringList string_list;
    for (int i = 0; i < dir.count(); ++i) {
        //文件名称
        QString file_name = dir[i];
        string_list.append(file_name);
//        qDebug() << string_list[i].toInt();
        tasks << string_list[i].toInt();
    }
}

QString ProcessInfo::getExe() const
{
    return exe;
}

void ProcessInfo::setExe(const qint64 &appPid)
{
    exe = appPid;
}

QString ProcessInfo::getCmdline() const
{
    return cmdline;
}

QList<qint64> ProcessInfo::getChildrenPid() const
{
    return childrenPid;
}

void ProcessInfo::setChildrenPid(const qint64 &appPid)
{

    std::string appChildrenPid = "pgrep -P " + QString::number(appPid).toStdString();
    FILE* fp = popen(appChildrenPid.c_str(),"r");
    char nameBuff[200] = "";
    for (int i = 0; fgets(nameBuff, 200, fp) != NULL; ++i) {
        std::string childrenInfo = nameBuff;
        std::string appChildrenInfo = std::string(childrenInfo.begin(), childrenInfo.begin() + childrenInfo.find('\n'));
        childrenPid << QString::fromStdString(appChildrenInfo).toInt();
//        qDebug() << __FUNCTION__ << "---" << childrenPid[i];
    }
    pclose(fp);
}

void ProcessInfo::setCmdline(const qint64 &appPid)
{
    std::ifstream inFile;
    std::string appCmdline;
    std::string procCmdline = "/proc/" + std::to_string(appPid) + ("/cmdline");
    inFile.open(procCmdline);
    if (!inFile.is_open()) {
        qWarning() << "Open file:" << procCmdline.c_str() << " failed";
        return;
    }
    getline(inFile, appCmdline);
    inFile.close();
    qDebug() << __FUNCTION__ << "---appCmdline---" << appCmdline.c_str();
    if (appCmdline.find("-e") != std::string::npos) {
        qDebug() << "---/usr/bin/mate-terminal-e---" << QString("/usr/bin/mate-terminal-e");
        cmdline = QString("/usr/bin/mate-terminal-e");
    } else {
        cmdline = appCmdline.c_str();
    }
}

void ProcessInfo::initProcessInfo(qint64 pid, QList<qint64> childrenPid, AppStatus status, QList<WindowId> wids, QStringList args)
{
    if (pid <= 0) {
        qWarning() << __FUNCTION__ << "pid不合法!!!";
        return;
    }
    setPid(pid);
    setChildrenPid(pid);
    setStatus(status);
    setWids(wids);
    setArgs(args);
    setTasks(pid);
    setExe(pid);
    setCmdline(pid);
}
