#pragma once

#include <string>
#include <chrono>
#include <memory>

namespace maps::mrc::drive {

enum class BatteryType
{
    LIION = 1,
    LIFEPO4 = 2
};

enum class BatteryLiveStatus
{
    Alive,
    Dead
};

class PowerManagerException : public std::exception {
 public:
    explicit PowerManagerException(const char* message);
    const char* what() const noexcept override;

 private:
    std::string message_;
};

class Battery
{
 public:
    Battery(
        int channel = 2,
        int address = 0x6b,
        BatteryType battery_ = BatteryType::LIION,
        bool doEnableBattery = false);

 public:
    double batteryVoltage() const;
    double inputVoltage() const;
    bool isChargerConnected() const;
    double batteryDischargeCurrent() const;
    double batteryChargeCurrent() const;

    void startCharging();
    void stopCharging();

    void setChargingVoltage();

    bool needCharging() const;
    bool isCharging() const;

    bool isBatteryOn() const;
    void enableBattery();
    void disableBattery();

    BatteryType batteryType() const;

    void updateBatteryLiveStatus();
    bool isBatteryAlive() const;

 private:
    bool checkHardware() const;

    void enableMonitoring();

    void setup(bool doEnableBattery);

    BatteryType detectBatteryType() const;

    int batteryVoltageToSet() const;

 private:
    bool isBatteryOn_;
    BatteryType batteryId_;
    BatteryLiveStatus batteryLiveStatus_;
    bool isCharging_;

    int wiringPiDesc_;
};

} // namespace maps::mrc::drive