#include "ukuistartup.h"
#include "ukuidisplay_p.h"

#include "ukui-startup-v1.h"
#include "ukui-startup-v2.h"

#include <QDebug>
#include <QFile>

UkuiStartupManager *ukuiStartupManager()
{
    static UkuiStartupManager *instance = nullptr;
    if (!instance) {
        instance = new UkuiStartupManager();
    }
    return instance;
}

class UkuiStartupManagerPrivate
{
public:
    UkuiStartupManagerPrivate();
    ~UkuiStartupManagerPrivate();

    void setStartupGeometryByPid(uint32_t pid, int x, int y, uint32_t width, uint32_t height);
    void setStartupGeometryEx(std::string appId, uint32_t pid, int x, int y, uint32_t width, uint32_t height);

private:
    wayland::ukui_startup_management_v1_t m_ukuiStartupManager;
    wayland::ukui_startup_management_v2_t m_ukuiStartupManagerV2;
};

UkuiStartupManagerPrivate::UkuiStartupManagerPrivate()
{
    //     m_ukuiStartupManager = static_cast<ukui_startup_management_v1 *>(ukui_startup_management_v1_interface.name, &ukui_startup_management_v1_interface, ukui_startup_management_v1_interface.version));
    //     m_ukuiStartupManagerV2 = static_cast<ukui_startup_management_v2 *>(ukuiDisplay()->bind(ukui_startup_management_v2_interface.name, &ukui_startup_management_v2_interface, ukui_startup_management_v2_interface.version));
}

UkuiStartupManagerPrivate::~UkuiStartupManagerPrivate()
{
}

void UkuiStartupManagerPrivate::setStartupGeometryByPid(uint32_t pid, int x, int y, uint32_t width, uint32_t height)
{
    if (width <= 0 || height <= 0) {
        qWarning() << "Invalid width or height for startup geometry";
        return;
    }

    if (m_ukuiStartupManagerV2) {
        auto start_info = m_ukuiStartupManagerV2.create_startup_info();
        start_info.set_startup_geometry(x, y, width, height);
        start_info.set_pid(pid);

        QFile file("/proc/" + QString::number(pid) + "/cmdline");
        if (file.open(QIODevice::ReadOnly)) {
            QByteArray raw = file.readAll();
            QString cmdline = QString::fromUtf8(raw).replace('\0', ' ');
            QString appId;
            if (!cmdline.trimmed().isEmpty()) {
                QStringList parts = cmdline.split(" ", Qt::SkipEmptyParts);
                if (!parts.isEmpty()) {
                    QString first = parts.first();
                    QStringList pathParts = first.split("/", Qt::SkipEmptyParts);
                    if (!pathParts.isEmpty()) {
                        appId = pathParts.last();
                    }
                }
            }
            if (!appId.isEmpty()) {
                start_info.set_appid(appId.toUtf8().constData());
            } else {
                qWarning() << "Failed to extract appId from cmdline:" << cmdline;
            }
        }

        wl_display_roundtrip(ukuiDisplay()->display());

    } else if (m_ukuiStartupManager) {
        m_ukuiStartupManager.set_startup_geometry(pid, x, y, width, height);
        wl_display_roundtrip(ukuiDisplay()->display());
    }
}

void UkuiStartupManagerPrivate::setStartupGeometryEx(std::string appId, uint32_t pid, int x, int y, uint32_t width, uint32_t height)
{
    if (width <= 0 || height <= 0) {
        qWarning() << "Invalid width or height for startup geometry";
        return;
    }

    if (m_ukuiStartupManagerV2) {
        auto start_info = m_ukuiStartupManagerV2.create_startup_info();
        start_info.set_startup_geometry(x, y, width, height);
        start_info.set_pid(pid);
        start_info.set_appid(appId);
        wl_display_roundtrip(ukuiDisplay()->display());
    } else if (m_ukuiStartupManager) {
        m_ukuiStartupManager.set_startup_geometry(pid, x, y, width, height);
        wl_display_roundtrip(ukuiDisplay()->display());
    }
}

UkuiStartupManager::UkuiStartupManager()
    : p(new UkuiStartupManagerPrivate())
{
}

UkuiStartupManager::~UkuiStartupManager()
{
    delete p;
    p = nullptr;
}

void UkuiStartupManager::setStartupGeometryByPid(uint32_t pid, int x, int y, uint32_t width, uint32_t height)
{
    p->setStartupGeometryByPid(pid, x, y, width, height);
}

void UkuiStartupManager::setStartupGeometryEx(std::string appId, uint32_t pid, int x, int y, uint32_t width, uint32_t height)
{
    p->setStartupGeometryEx(appId, pid, x, y, width, height);
}