#pragma once
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_BMP280.h>

/**
 * @brief Драйвер цифрового датчика давления и температуры BMP280 (Bosch Sensortec).
 * Обёртка над Adafruit_BMP280 с единым для репозитория API: Data/isAlive()/DI.
 */
class Bmp280Driver {
public:
    struct Data {
        float temperatureC; // Температура, °C
        float pressurePa;   // Давление, Па (СИ)
        float altitudeM;    // Оценочная высота над уровнем моря, м (по барометрической формуле)
    };

    // Адрес I2C зависит от уровня на пине SDO модуля: GND -> 0x76, VDD -> 0x77.
    // Источник: Bosch BMP280 datasheet DS001, rev.1.26 (10/2021), разд. 5.2 "I2C Interface".
    static constexpr uint8_t I2C_ADDRESS_SDO_LOW = 0x76;
    static constexpr uint8_t I2C_ADDRESS_SDO_HIGH = 0x77;

    /**
     * @param wire Ссылка на интерфейс I2C (Dependency Injection)
     * @param i2cAddress Адрес датчика (0x76 или 0x77 — см. I2C_ADDRESS_SDO_*)
     */
    explicit Bmp280Driver(TwoWire &wire = Wire, uint8_t i2cAddress = I2C_ADDRESS_SDO_HIGH);

    /**
     * @brief Инициализация датчика на шине I2C и настройка режима опроса.
     * @param sda Пин SDA
     * @param scl Пин SCL
     * @return true если датчик найден и его chip_id совпал с ожидаемым
     */
    bool begin(int sda = 21, int scl = 22);

    /**
     * @brief Опрос датчика (режим NORMAL — данные уже готовы в регистрах, чтение быстрое).
     * @return true если прочитанные значения физически правдоподобны
     */
    bool update();

    /// Последние успешно прочитанные данные.
    const Data& getData() const { return _data; }

    /// Давление на уровне моря (QNH) для расчёта высоты, гПа. По умолчанию — среднее для стандартной атмосферы.
    void setSeaLevelPressureHpa(float hpa) { _seaLevelHpa = hpa; }

    /// Пришли ли новые данные с датчика за последние timeoutMs (жива ли физическая связь по I2C).
    bool isAlive(unsigned long timeoutMs = 2000) const {
        return (millis() - _lastUpdateTime) < timeoutMs;
    }

private:
    TwoWire* _wire;
    uint8_t _i2cAddress;
    Adafruit_BMP280 _sensor;
    Data _data{};
    unsigned long _lastUpdateTime = 0;
    float _seaLevelHpa = 1013.25f; // Среднее давление на уровне моря, стандартная атмосфера ISA

    // Chip ID регистра 0xD0 "id", ожидаемое значение для BMP280.
    // Источник: Bosch BMP280 datasheet DS001, rev.1.26, Table 18 "Memory map", стр.24.
    static constexpr uint8_t CHIP_ID = 0x58;

    // Рабочий диапазон давления датчика — используется для отбраковки заведомо неверных показаний.
    // Источник: Bosch BMP280 datasheet DS001, rev.1.26, Table 2 "Parameter specification", стр.7.
    static constexpr float PRESSURE_MIN_PA = 30000.0f;  // 300 гПа
    static constexpr float PRESSURE_MAX_PA = 110000.0f; // 1100 гПа
};
