#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_MAX13865DEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_MAX13865DEFINITIONS_H_

#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>

#include "objects/systemObjectList.h"

namespace MAX31865 {

enum class PoolIds : lp_id_t { RTD_VALUE, TEMPERATURE_C, LAST_FAULT_BYTE, FAULT_BYTE };
enum Wires : unsigned int { TWO_WIRE = 0, THREE_WIRE = 1, FOUR_WIRE = 0 };

enum ConvMode : unsigned int { NORM_OFF = 0, AUTO = 1 };

enum Bias : unsigned int { OFF = 0, ON = 1 };

enum FilterSel : unsigned int { FIFTY_HERTZ = 1, SIXTY_HERTZ = 0 };

enum CfgBitPos {
  FILTER_SEL = 0,
  FAULT_STATUS_CLEAR = 1,
  FDCC = 2,
  WIRE_SEL = 4,
  ONE_SHOT = 5,
  CONV_MODE = 6,
  BIAS_SEL = 7
};

static constexpr uint32_t WARMUP_MS = 100;

static constexpr uint8_t WRITE_BIT = 0b10000000;

enum Regs : uint8_t {
  CONFIG = 0x00,
  RTD = 0x01,
  HIGH_THRESHOLD = 0x03,
  LOW_THRESHOLD = 0x05,
  FAULT_BYTE = 0x07
};

static constexpr DeviceCommandId_t CONFIG_CMD = 0x80;
static constexpr DeviceCommandId_t WRITE_HIGH_THRESHOLD = 0x83;
static constexpr DeviceCommandId_t WRITE_LOW_THRESHOLD = 0x85;

static constexpr DeviceCommandId_t REQUEST_CONFIG = CONFIG;
static constexpr DeviceCommandId_t REQUEST_RTD = RTD;
static constexpr DeviceCommandId_t REQUEST_HIGH_THRESHOLD = HIGH_THRESHOLD;
static constexpr DeviceCommandId_t REQUEST_LOW_THRESHOLD = LOW_THRESHOLD;
static constexpr DeviceCommandId_t REQUEST_FAULT_BYTE = FAULT_BYTE;
static constexpr DeviceCommandId_t CLEAR_FAULT_BYTE = 0x08;

static constexpr uint32_t MAX31865_SET_ID = REQUEST_RTD;
static constexpr uint8_t CLEAR_FAULT_BIT_VAL = 0b0000'0010;

static constexpr size_t MAX_REPLY_SIZE = 5;

class PrimarySet : public StaticLocalDataSet<4> {
 public:
  /**
   * Constructor used by owner and data creators like device handlers.
   * @param owner
   * @param setId
   */
  PrimarySet(HasLocalDataPoolIF* owner, uint32_t setId) : StaticLocalDataSet(owner, setId) {}

  /**
   * Constructor used by data users like controllers.
   * @param sid
   */
  PrimarySet(object_id_t objectId, uint32_t setId) : StaticLocalDataSet(sid_t(objectId, setId)) {}

  lp_var_t<float> rtdValue =
      lp_var_t<float>(sid.objectId, static_cast<lp_id_t>(PoolIds::RTD_VALUE), this);
  lp_var_t<float> temperatureCelcius =
      lp_var_t<float>(sid.objectId, static_cast<lp_id_t>(PoolIds::TEMPERATURE_C), this);
  lp_var_t<uint8_t> lastErrorByte =
      lp_var_t<uint8_t>(sid.objectId, static_cast<lp_id_t>(PoolIds::LAST_FAULT_BYTE), this);
  lp_var_t<uint8_t> errorByte =
      lp_var_t<uint8_t>(sid.objectId, static_cast<lp_id_t>(PoolIds::FAULT_BYTE), this);
};

}  // namespace MAX31865

namespace EiveMax31855 {

static constexpr float RTD_RREF_PT1000 = 4020.0;  //!< Ohm
static constexpr uint8_t NUM_RTDS = 16;

enum RtdCommands : DeviceCommandId_t {
  ON = 0,
  EXCHANGE_SET_ID = MAX31865::REQUEST_RTD,
  ACTIVE = 2,
  LOW_THRESHOLD = 3,
  HIGH_TRESHOLD = 4,
  OFF = 5,
  CFG = 6,
  NUM_CMDS
};

class ReadOutStruct : public SerialLinkedListAdapter<SerializeIF> {
 public:
  ReadOutStruct() { setLinks(); }
  ReadOutStruct(bool active, uint32_t spiErrCnt, bool faultBitSet, uint8_t faultVal,
                uint16_t rtdVal)
      : active(active),
        adcCode(rtdVal),
        faultBitSet(faultBitSet),
        faultValue(faultVal),
        spiErrorCount(spiErrCnt) {
    setLinks();
  }

  //! RTD was set on and is configured, but is not periodically polled
  SerializeElement<bool> configured = false;
  //! RTD is active and polled periodically
  SerializeElement<bool> active = false;
  SerializeElement<uint16_t> adcCode = 0;
  SerializeElement<bool> faultBitSet = false;
  SerializeElement<uint8_t> faultValue = 0;
  SerializeElement<uint32_t> spiErrorCount = 0;

 private:
  void setLinks() {
    setStart(&configured);
    configured.setNext(&active);
    active.setNext(&adcCode);
    adcCode.setNext(&faultBitSet);
    faultBitSet.setNext(&faultValue);
    faultValue.setNext(&spiErrorCount);
  };
};

};  // namespace EiveMax31855

#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_MAX13865DEFINITIONS_H_ */