text: // This file is part of Projecteur - https://github.com/jahnf/projecteur
  // - See LICENSE.md and README.md
  #pragma once
  
  #include "device-defs.h"
  
  #include <QPointer>
  #include <QWidget>
  
  #include <map>
  #include <vector>
  #include <utility>
  
  class DeviceConnection;
  class InputMapper;
  class MultiTimerWidget;
  class QComboBox;
  class QTabWidget;
  class QTextEdit;
  class Settings;
  class Spotlight;
  class VibrationSettingsWidget;
  class SubDeviceConnection;
  class SubHidppConnection;
  class TimerTabWidget;
  
  // -------------------------------------------------------------------------------------------------
  class DevicesWidget : public QWidget
  {
    Q_OBJECT
  
  public:
    explicit DevicesWidget(Settings* settings, Spotlight* spotlight, QWidget* parent = nullptr);
    DeviceId currentDeviceId() const;
  
  signals:
    void currentDeviceChanged(const DeviceId&);
  
  private:
    QWidget* createDisconnectedStateWidget();
    void createDeviceComboBox(Spotlight* spotlight);
    QWidget* createDevicesWidget(Settings* settings, Spotlight* spotlight);
    QWidget* createInputMapperWidget(Settings* settings, Spotlight* spotlight);
    QWidget* createDeviceInfoWidget(Spotlight* spotlight);
    TimerTabWidget* createTimerTabWidget(Settings* settings, Spotlight* spotlight);
    void updateTimerTab(Spotlight* spotlight);
  
    QComboBox* m_devicesCombo = nullptr;
    QTabWidget* m_tabWidget = nullptr;
    TimerTabWidget* m_timerTabWidget = nullptr;
    QPointer<QObject> m_timerTabContext;
    QWidget* m_deviceDetailsTabWidget = nullptr;
  
    QPointer<InputMapper> m_inputMapper;
  };
  
  // -------------------------------------------------------------------------------------------------
  class TimerTabWidget : public QWidget
  {
    Q_OBJECT
  
  public:
    TimerTabWidget(Settings* settings, QWidget* parent = nullptr);
    VibrationSettingsWidget* vibrationSettingsWidget();
  
    void loadSettings(const DeviceId& deviceId);
    void setSubDeviceConnection(SubDeviceConnection* sdc);
  
  private:
    DeviceId m_deviceId;
    Settings* const m_settings = nullptr;
    MultiTimerWidget* m_multiTimerWidget = nullptr;
    VibrationSettingsWidget* m_vibrationSettingsWidget = nullptr;
  };
  
  // -------------------------------------------------------------------------------------------------
  class DeviceInfoWidget : public QWidget
  {
    Q_OBJECT
  
  public:
    DeviceInfoWidget(QWidget* parent = nullptr);
    void setDeviceConnection(DeviceConnection* connection);
  
  private:
    void initSubdeviceInfo();
    void updateSubdeviceInfo(SubDeviceConnection* sdc);
    void connectToSubdeviceUpdates(SubDeviceConnection* sdc);
    void connectToBatteryUpdates(SubHidppConnection* hdc);
    void updateHidppInfo(SubHidppConnection* hdc);
    void updateBatteryInfo(SubHidppConnection* hdc);
  
    void delayedTextEditUpdate();
    void updateTextEdit();
  
    QTextEdit* m_textEdit = nullptr;
    QTimer* m_delayedUpdateTimer = nullptr;
    QTimer* m_batteryInfoTimer = nullptr;
  
    std::vector<std::pair<QString, QString>> m_deviceBaseInfo;
  
    struct SubDeviceInfo {
      QString info;
      bool isHidpp = false;
      bool hasBatteryInfo = false;
    };
  
    std::map<QString, SubDeviceInfo> m_subDevices;
    QString m_batteryInfo;
  
    struct HidppInfo {
      QString receiverState;
      QString presenterState;
      QString protocolVersion;
      QStringList hidppFlags;
  
      void clear()
      {
        receiverState.clear();
        presenterState.clear();
        protocolVersion.clear();
        hidppFlags.clear();
      }
    };
  
    HidppInfo m_hidppInfo;
  
    QPointer<QObject> m_connectionContext;
    QPointer<DeviceConnection> m_connection;
  };