#pragma once

#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include <QByteArray>
#include <QString>

class Sensor {
  public:
    ~Sensor();

    std::vector<float> readValues();

    operator bool() const { return !m_errorOccurred; }

  private:
    friend std::vector<Sensor> enumerateSensors();

    static constexpr auto VERSION_CMD = std::string_view{"version"};
    static constexpr auto RANGE_CMD = std::string_view{"range"};
    static constexpr auto READ_CMD = std::string_view{"read csv"};

    static constexpr auto SUPPORTED_FIRMWARE = std::string_view{"AdaptiveBrightness v1.2"};

    const QString m_serialPortName;
    bool m_errorOccurred = false;

    std::optional<std::pair<int, int>> m_range;

    Sensor(const QString& serialPortName);

    bool isValidSensor();

    bool getSensorCommandResponse(const QString& serialPortName, QByteArray command, QByteArray& response);

    std::string parseVersionResponse(const QByteArray& response) const;
    std::pair<int, int> parseRangeResponse(const QByteArray& response) const;
    std::vector<int> parseReadResponse(const QByteArray& response) const;

    std::pair<int, int> readRange();
};
