#ifndef TG_LTR_390_H
#define TG_LTR_390_H

#include <Wire.h>

#define LTR390_ADDRESS (0x53)


//////////////////////////////////////////////////////////////////
/// LTR390 - Driver class for Ltr390 sensor
///
/// Based on the data sheet provided
///
class LTR390 {
public:

    typedef enum {
        LTR390_ON = 0x2,
        LTR390_MODE_ALS = 0x0,
        LTR390_MODE_UVS = 0x8,
    } ltr390_mode_t;

    /*!    @brief  Sensor gain for UV or ALS  */
    typedef enum {
        LTR390_GAIN_1 = 0,
        LTR390_GAIN_3 = 1,
        LTR390_GAIN_6 = 2,
        LTR390_GAIN_9 = 3,
        LTR390_GAIN_18 = 4,
    } ltr390_gain_t;

    /*!    @brief Measurement resolution (higher res means slower reads!)  */
    typedef enum {
        LTR390_RESOLUTION_20BIT = 0x0,
        LTR390_RESOLUTION_19BIT = 0x10,
        LTR390_RESOLUTION_18BIT = 0x20,
        LTR390_RESOLUTION_17BIT = 0x30,
        LTR390_RESOLUTION_16BIT = 0x40,
        LTR390_RESOLUTION_13BIT = 0x50,
    } ltr390_resolution_t;


    /*!    @brief Measurement resolution (higher res means slower reads!)  */
    typedef enum {
        LTR390_RATE_25 = 0x0,
        LTR390_RATE_50 = 0x1,
        LTR390_RATE_100 = 0x2,
        LTR390_RATE_200 = 0x3,
        LTR390_RATE_500 = 0x4,
        LTR390_RATE_1000 = 0x5,
        LTR390_RATE_2000 = 0x6,
    } ltr390_rate_t;

    enum ChipModel {
        ChipModel_UNKNOWN = 0,
        ChipModel_LTR390_REV0 = 0xB0,
        ChipModel_LTR390_REV1 = 0xB1,
        ChipModel_LTR390_REV2 = 0xB2,
        ChipModel_LTR390_REV3 = 0xB3,
    };

    LTR390(TwoWire* i2c): m_initialized(false),i2c(i2c) {}

    ChipModel chipModel();

    bool begin();
    bool reset();

    uint32_t uv();
    void read(uint32_t& uv, uint32_t& uvi);


protected:
    bool Initialize();
    void InitializeFilter();


private:
    TwoWire* i2c;
    ChipModel m_chip_model;
    bool m_initialized;

    static const uint8_t MAIN_CTRL = 0x00;       ///< Main control register
    static const uint8_t MEAS_RATE = 0x04;       ///< Resolution and data rate
    static const uint8_t GAIN = 0x05;            ///< ALS and UVS gain range
    static const uint8_t ID_ADDR = 0x06;         ///< Part id/revision register
    static const uint8_t MAIN_STATUS = 0x07;     ///< Main status register
    static const uint8_t ALSDATA = 0x0D;         ///< ALS data lowest byte
    static const uint8_t UVSDATA = 0x10;         ///< UVS data lowest byte
    static const uint8_t INT_CFG = 0x19;         ///< Interrupt configuration
    static const uint8_t INT_PST = 0x1A;         ///< Interrupt persistance config
    static const uint8_t THRESH_UP = 0x21;       ///< Upper threshold, low byte
    static const uint8_t THRESH_LOW = 0x24;      ///< Lower threshold, low byte

    static const uint8_t RESET_ADDR = 0x00;      ///< Reset Address
    static const uint8_t RESET_VALUE = 0x10;      ///< Reset value

    static const uint8_t SENSOR_DATA_LENGTH = 3; //For 16 bit resolution !

    bool ReadChipID();
    bool ReadTrim();

    bool ReadData(int32_t data[SENSOR_DATA_LENGTH], uint32_t addr);
    bool ReadRegister(uint8_t addr,uint8_t data[],uint8_t length);

    void WriteSettings();
    bool WriteRegister(uint8_t addr,uint8_t data);
};

#endif