#ifndef _TUSBProvider_h__
#define _TUSBProvider_h__

#include <QMap>
#include <QMutex>
#include <QObject>
#include <QSet>
#include <QVector>

#include "TProvider.h"

class USBThread;

/**
 * Singleton class
 */
class TUSBProvider : public TProvider {

    friend class USBThread;

    Q_OBJECT

  public:
    // Singleton instance
    static TUSBProvider &instance() {
        static TUSBProvider instance;
        return instance;
    }

    virtual ~TUSBProvider();

    // Disable copy constructor and assignment operator
    // Required to enforce singleton pattern
    TUSBProvider(TUSBProvider const &) = delete;
    void operator=(TUSBProvider const &) = delete;

    virtual int getDeviceCount();
    virtual QVector<TDevice *> getDevices();
    virtual TDevice *findDevice(const QString &serialNumber);

    virtual int start();
    virtual void shutdown();

    virtual void setPollInterval(int ms);
    virtual void setVirtualOptions(unsigned int flags, double slp);
    virtual void setUserCalibration(const QString &serialNumber, int channelIndex, bool on);

    int setUserCalibrationPoint(TChannel *channel, int id, double x, double y);

    // Commands for specific products
    int set_DXC120_ASC(const QString &serialNumber, int value);
    int get_DXC120_ASC(const QString &serialNumber);
    int set_DXC120_FRC(const QString &serialNumber, int value);
    int set_DXC220_KZ(const QString &serialNumber, int value);
    int set_DXC300_KS(const QString &serialNumber, int value, int offset = 0);

    bool isServiceRunning();

  private:
    TUSBProvider();

    QMap<QString, TDevice *> devicesBySerialNumber;
    QSet<QString> disconnectedSerialNumbers;

    QMutex mutex;

    TDevice *tickerDevice;

    void tick(int64_t timestamp);
    void addSource(Source *source);
    void updateSource(Source *source);
};

#endif
