#ifndef _LoggingThread_h__
#define _LoggingThread_h__

#include <QLinkedList>
#include <QMap>
#include <QMutex>
#include <QVector>
#include <QWaitCondition>

#include "Config.h"
#include "DaemonThread.h"
#include "DataTable.h"
#include "TChannel.h"
#include "TDevice.h"
#include "TDeviceSignal.h"
#include "csv.h"
#include "datalog.h"
#include "queue.h"

#include <dracal/logging/logger/interval.hpp>
#include <memory>

class LoggingThread : public DaemonThread {

    Q_OBJECT

  public:
    enum Error { ERROR_OPEN_OUTPUT };

    LoggingThread(const QVector<QString> &channelIDs, const QString &path, const QString &comment, int interval,
                  bool append = false);
    virtual ~LoggingThread();

    virtual void run();
    virtual void shutdown();

  signals:

    void error(int code);
    void written(qulonglong n);

  private:
    enum State { READY, SHUTDOWN };

    QMutex mutex;
    QWaitCondition condition;

    // Members that are read-only after construction (no need to lock mutex)
    const QString path;
    const int channelCount;
    const char *fileMode;
    const int64_t origin;
    const int64_t interval_us;
    QMap<QString, TDeviceSignal *> deviceSignalBySerial;
    List channelHeaders;

    // Members accessed by local thread only (no need to lock mutex)
    DataTable *table;
    DataLog datalog;
    CSV_Options csvopt;
    CSV csv;
    qulonglong lineCounter;

    // New interval logger
    std::unique_ptr<dracal::logging::interval_logger> _interval_logger;

    // Members accessed by application thread and local thread (MUST LOCK MUTEX)
    State state = READY;
    Queue events;

    int decimal_point_index = 0;

    chrono::time_point<chrono::steady_clock> _last_check{};

    // Private methods
    bool processEvents();
    void writeRows();

  private slots:

    // All slots invoked by main application thread (MUST LOCK MUTEX)

    void onDeviceConnected(const TDevice *device);
    void onDeviceDisconnected(const TDevice *device);
    void onDeviceUpdated(const TDevice *device);

    void addEvent(const TDevice *device);

  private:
#if defined(Q_OS_MAC)
    MacSleepInhibitor sleep;
#endif
};

#endif
