// Copyright (C) 2023-2026 JiDe Zhang <zhangjide@deepin.org>.
// SPDX-License-Identifier: Apache-2.0 OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#pragma once

#include <wglobal.h>
#include <QObject>
#include <qwglobal.h>
#include <QMap>
#include <QMutex>

QW_BEGIN_NAMESPACE
class qw_input_device;
QW_END_NAMESPACE

QT_BEGIN_NAMESPACE
class QInputDevice;
class QEventPoint;
QT_END_NAMESPACE

WAYLIB_SERVER_BEGIN_NAMESPACE

class WSeat;
class WInputDevicePrivate;

// Internal helper for parsing /proc/bus/input/devices
struct ProcDeviceInfo {
    QString name;
    QString physPath;

    bool isValid() const {
        return !name.isEmpty() && !physPath.isEmpty();
    }
};

class DeviceInfoParser {
public:
    static DeviceInfoParser& instance();

    QString getPhysicalPath(const QString& deviceName);

private:
    DeviceInfoParser() = default;
    void refreshDeviceInfo();
    void parseDeviceBlock(const QString& block);

    QMap<QString, ProcDeviceInfo> m_deviceMap;
    QMutex m_mutex;
};
class WAYLIB_SERVER_EXPORT WInputDevice : public WWrapObject
{
    W_DECLARE_PRIVATE(WInputDevice)
public:
    enum class Type {
        Unknow,
        Keyboard,
        Pointer,
        Touch,
        Tablet,
        TabletPad,
        Switch
    };
    Q_ENUM(Type)

    WInputDevice(QW_NAMESPACE::qw_input_device *handle);

    QW_NAMESPACE::qw_input_device *handle() const;

    static WInputDevice *fromHandle(const QW_NAMESPACE::qw_input_device *handle);

    template<class QInputDevice>
    inline QInputDevice *qtDevice() const {
        return qobject_cast<QInputDevice*>(qtDevice());
    }
    QInputDevice *qtDevice() const;
    static WInputDevice *from(const QInputDevice *device);

    Type type() const;
    QString name() const;
    void setSeat(WSeat *seat);
    WSeat *seat() const;
    QString devicePath() const;

private:
    friend class QWlrootsIntegration;
    friend class WSeat;
    friend class WSeatPrivate;
    void setQtDevice(QInputDevice *device);

    void setExclusiveGrabber(QObject *grabber);
    QObject *exclusiveGrabber() const;

    QObject *hoverTarget() const;
    void setHoverTarget(QObject *object);
};

WAYLIB_SERVER_END_NAMESPACE
