#ifndef MISSION_DEVICES_MAX31865PT1000HANDLER_H_
#define MISSION_DEVICES_MAX31865PT1000HANDLER_H_

#include <OBSWConfig.h>
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>

#include <array>
#include <cstdint>

#include "devicedefinitions/Max31865Definitions.h"

/**
 * @brief       Device Handler for the thermal sensors
 * @details
 * Documentation of devices:
 * MAX31865 RTD converter:
 * https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
 * Pt1000 platinum resistance thermometers OMEGA F2020-1000-1/3B:
 * https://br.omega.com/omegaFiles/temperature/pdf/F1500_F2000_F4000.pdf
 *
 * The thermal sensor values are measured using the MAX31865 RTD converter IC
 * which creates digital values from the measured resistance of the Pt1000
 * devices which can be read with the SPI interface.
 * Refer to the SOURCE system schematic for the exact setup and number
 * of devices.
 *
 * @author      R. Mueller
 * @ingroup     devices
 */
class Max31865PT1000Handler : public DeviceHandlerBase {
 public:
  Max31865PT1000Handler(object_id_t objectId, object_id_t comIF, CookieIF *comCookie);
  virtual ~Max31865PT1000Handler();

  // Configuration in 8 digit code:
  // 1. 1 for V_BIAS enabled, 0 for disabled
  // 2. 1 for Auto-conversion, 0 for off
  // 3. 1 for 1-shot enabled, 0 for disabled (self-clearing bit)
  // 4. 1 for 3-wire enabled, 0 for disabled (two and four wired RTD)
  // 5./6. Fault detection:  00 for no action, 01 for automatic delay, 1
  // 	  0 for run fault detection with manual delay,
  // 	  11 for finish fault detection with manual delay
  // 7. Fault status:  Write 1 to reset fault status register (Bit is self cleared afterwards)
  // 8. 1 for 50 Hz filter, 0 for 60 Hz filter (noise rejection filter)
  static constexpr uint8_t DEFAULT_CONFIG = 0b11000001;

  void setInstantNormal(bool instantNormal);
  void setDeviceIdx(uint8_t idx);

  /**
   * Expected temperature range is -100 C and 100 C.
   * If there are temperatures beyond this range there must be a fault.
   * The threshold variables cause the MAX1385 to signal an error in case the measured resistance
   * indicates a temperature higher than 100 C or lower than -100 C.
   * Default settings of MAX13865 are 0xFFFF for the high threshold register and 0x0 for the
   * low threshold register.
   */
  static constexpr uint16_t HIGH_THRESHOLD = 11298;  // = 100 C
  static constexpr uint16_t LOW_THRESHOLD = 4902;    // = -100 C

  static constexpr float RTD_RREF_PT1000 = 4020.0;         //!< Ohm
  static constexpr float RTD_RESISTANCE0_PT1000 = 1000.0;  //!< Ohm
 protected:
  // DeviceHandlerBase abstract function implementation
  void doStartUp() override;
  void doShutDown() override;
  ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
  ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
  ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
                                        size_t commandDataLen) override;
  void fillCommandAndReplyMap() override;
  ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId,
                             size_t *foundLen) override;
  ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
  uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
  ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;

  void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
                      uint32_t parameter = 0) override;
  ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
                                        LocalDataPoolManager &poolManager) override;
  void modeChanged() override;

 private:
  uint8_t switchId = 0;
  bool instantNormal = false;
  bool warningSwitch = true;

  enum class InternalState {
    NONE,
    WARMUP,
    CONFIGURE,
    CONFIG_HIGH_THRESHOLD,
    REQUEST_HIGH_THRESHOLD,
    CONFIG_LOW_THRESHOLD,
    REQUEST_LOW_THRESHOLD,
    REQUEST_CONFIG,
    RUNNING,
    REQUEST_FAULT_BYTE,
    CLEAR_FAULT_BYTE
  };

  InternalState internalState = InternalState::NONE;
  bool commandExecuted = false;

  bool resetFaultBit = false;
  dur_millis_t startTime = 0;
  uint8_t faultByte = 0;
  uint8_t deviceIdx = 0;
  std::array<uint8_t, 3> commandBuffer{0};

  Max31865Definitions::Max31865Set sensorDataset;
  sid_t sensorDatasetSid;

#if OBSW_VERBOSE_LEVEL >= 1
  PeriodicOperationDivider *debugDivider;
#endif
};

#endif /* MISSION_DEVICES_MAX31865PT1000HANDLER_H_ */