#ifndef DEVICELISTMODEL_H
#define DEVICELISTMODEL_H

#include <QAbstractListModel>
#include <QQmlEngine>

class QUdpSocket;
class DeviceConnection;

class DeviceListModel : public QAbstractListModel {
    Q_OBJECT
    QML_ELEMENT
    QML_UNCREATABLE("Only used in C++...")
    Q_PROPERTY(bool isSearching READ isSearching NOTIFY isSearchingChanged)
    Q_PROPERTY(float searchProgress READ searchProgress NOTIFY searchProgressChanged)

public:
    static constexpr uint16_t BroadcastPort = 40000;
    static constexpr uint16_t ListenPort = 40001;
    static constexpr int RetryCount = 10;
    enum InfoRoles {
        DeviceIdRole = Qt::UserRole + 1,
        FirmwareVersionRole,
        SoftwareVersionRole,
        IpRole,
        OnlineStatusRole,
    };
    DeviceListModel(QObject *parent = nullptr);
    int rowCount(const QModelIndex &parent = QModelIndex()) const final;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const final;
    QHash<int, QByteArray> roleNames() const final;
    Q_INVOKABLE QVariantMap get(int index) const;
    std::shared_ptr<DeviceConnection> device(int index);
    void startSearchDevice();
    bool isSearching() const;
    float searchProgress() const;

signals:
    void isSearchingChanged();
    void searchProgressChanged();

protected:
    void onDeviceConnected();
    void onDeviceDisconnected();
    void onDeviceReplyReadyRead();
    void broadcast();
    void stopSearchDevice();
    void timerEvent(QTimerEvent *event);

private:
    std::vector<std::shared_ptr<DeviceConnection>> m_devices;
    std::list<QUdpSocket *> m_udpSockets;
    QUdpSocket *m_broadcastSocket = nullptr;
    int m_timerId = -1;
    int m_retries = 0;
};

#endif // DEVICELISTMODEL_H