// SPDX-FileCopyrightText: 2026 Marco Allegretti
// SPDX-License-Identifier: EUPL-1.2

#include "devicecontext.h"

#include <KRuntimePlatform>

#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QGuiApplication>
#include <QInputDevice>
#include <QJSEngine>
#include <QQmlEngine>
#include <QScreen>

#include <algorithm>

namespace
{
bool pathExists(const QString &path)
{
    return QFileInfo::exists(path);
}

bool systemHasBattery()
{
    const QDir powerSupply(QStringLiteral("/sys/class/power_supply"));
    const QStringList entries = powerSupply.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
    for (const QString &entry : entries) {
        if (entry.startsWith(QStringLiteral("BAT"), Qt::CaseInsensitive)) {
            return true;
        }
        if (pathExists(powerSupply.filePath(entry + QStringLiteral("/type")))) {
            QFile typeFile(powerSupply.filePath(entry + QStringLiteral("/type")));
            if (typeFile.open(QIODevice::ReadOnly) && QString::fromUtf8(typeFile.readAll()).trimmed() == QLatin1String("Battery")) {
                return true;
            }
        }
    }
    return false;
}
}

DeviceContext::DeviceContext(QObject *parent)
    : QObject(parent)
    , m_runtimePlatform(KRuntimePlatform::runtimePlatform().join(QLatin1Char(',')))
    , m_hasBattery(systemHasBattery())
{
    const QList<const QInputDevice *> devices = QInputDevice::devices();
    for (const QInputDevice *device : devices) {
        if (!device) {
            continue;
        }
        const auto type = device->type();
        m_hasTouch = m_hasTouch || type == QInputDevice::DeviceType::TouchScreen;
        m_hasKeyboard = m_hasKeyboard || type == QInputDevice::DeviceType::Keyboard;
        m_hasMouse = m_hasMouse || type == QInputDevice::DeviceType::Mouse;
    }

    const QList<QScreen *> screens = QGuiApplication::screens();
    m_displayCount = std::max(1, static_cast<int>(screens.size()));
    if (QScreen *screen = QGuiApplication::primaryScreen()) {
        const QSize size = screen->geometry().size();
        m_primaryDisplayLandscape = size.width() >= size.height();
    }

    const QString platform = m_runtimePlatform;
    if (m_displayCount > 1) {
        m_recommendedDeviceClass = QStringLiteral("dual-screen");
        m_recommendedExperienceProfile = QStringLiteral("hybrid");
    } else if (platform.contains(QStringLiteral("phone"))) {
        m_recommendedDeviceClass = QStringLiteral("phone");
        m_recommendedExperienceProfile = QStringLiteral("mobile");
    } else if (platform.contains(QStringLiteral("handheld"))) {
        m_recommendedDeviceClass = QStringLiteral("handheld");
        m_recommendedExperienceProfile = QStringLiteral("gaming");
    } else if (platform.contains(QStringLiteral("tablet"))) {
        m_recommendedDeviceClass = QStringLiteral("tablet");
        m_recommendedExperienceProfile = QStringLiteral("mobile");
    } else if (m_hasBattery && m_hasTouch && (m_hasKeyboard || m_hasMouse)) {
        m_recommendedDeviceClass = QStringLiteral("tablet");
        m_recommendedExperienceProfile = QStringLiteral("hybrid");
    } else if (m_hasBattery && (m_hasKeyboard || m_hasMouse)) {
        m_recommendedDeviceClass = QStringLiteral("laptop");
        m_recommendedExperienceProfile = QStringLiteral("desktop");
    } else if (!m_hasBattery && !m_hasTouch) {
        m_recommendedDeviceClass = QStringLiteral("desktop");
        m_recommendedExperienceProfile = QStringLiteral("desktop");
    } else {
        m_recommendedDeviceClass = QStringLiteral("tablet");
        m_recommendedExperienceProfile = QStringLiteral("mobile");
    }
}

DeviceContext *DeviceContext::self()
{
    static auto *instance = new DeviceContext(qApp);
    return instance;
}

DeviceContext *DeviceContext::create(QQmlEngine *qmlEngine, QJSEngine *jsEngine)
{
    Q_UNUSED(qmlEngine)
    Q_UNUSED(jsEngine)
    return self();
}

QString DeviceContext::runtimePlatform() const
{
    return m_runtimePlatform;
}

QString DeviceContext::recommendedDeviceClass() const
{
    return m_recommendedDeviceClass;
}

QString DeviceContext::recommendedExperienceProfile() const
{
    return m_recommendedExperienceProfile;
}

bool DeviceContext::hasTouch() const
{
    return m_hasTouch;
}

bool DeviceContext::hasKeyboard() const
{
    return m_hasKeyboard;
}

bool DeviceContext::hasMouse() const
{
    return m_hasMouse;
}

bool DeviceContext::hasBattery() const
{
    return m_hasBattery;
}

int DeviceContext::displayCount() const
{
    return m_displayCount;
}

bool DeviceContext::hasExternalDisplay() const
{
    return m_displayCount > 1;
}

bool DeviceContext::primaryDisplayLandscape() const
{
    return m_primaryDisplayLandscape;
}
