#include "TemperatureSensorsDummy.h"

#include <objects/systemObjectList.h>

#include <cmath>
#include <cstdlib>

TemperatureSensorsDummy::TemperatureSensorsDummy()
    : ExtendedControllerBase(objects::RTD_0_IC3_PLOC_HEATSPREADER, objects::NO_OBJECT),
      max31865Set(this, MAX31865::MAX31865_SET_ID) {
  ObjectManager::instance()->insert(objects::RTD_1_IC4_PLOC_MISSIONBOARD, this);
  ObjectManager::instance()->insert(objects::RTD_2_IC5_4K_CAMERA, this);
  ObjectManager::instance()->insert(objects::RTD_3_IC6_DAC_HEATSPREADER, this);
  ObjectManager::instance()->insert(objects::RTD_4_IC7_STARTRACKER, this);
  ObjectManager::instance()->insert(objects::RTD_5_IC8_RW1_MX_MY, this);
  ObjectManager::instance()->insert(objects::RTD_6_IC9_DRO, this);
  ObjectManager::instance()->insert(objects::RTD_7_IC10_SCEX, this);
  ObjectManager::instance()->insert(objects::RTD_8_IC11_X8, this);
  ObjectManager::instance()->insert(objects::RTD_9_IC12_HPA, this);
  ObjectManager::instance()->insert(objects::RTD_10_IC13_PL_TX, this);
  ObjectManager::instance()->insert(objects::RTD_11_IC14_MPA, this);
  ObjectManager::instance()->insert(objects::RTD_12_IC15_ACU, this);
  ObjectManager::instance()->insert(objects::RTD_13_IC16_PLPCDU_HEATSPREADER, this);
  ObjectManager::instance()->insert(objects::RTD_14_IC17_TCS_BOARD, this);
  ObjectManager::instance()->insert(objects::RTD_15_IC18_IMTQ, this);
  ObjectManager::instance()->insert(objects::TMP1075_HANDLER_1, this);
  ObjectManager::instance()->insert(objects::TMP1075_HANDLER_2, this);
}

ReturnValue_t TemperatureSensorsDummy::initialize() {
  static bool done = false;
  if (not done) {
    done = true;
    ReturnValue_t result = ExtendedControllerBase::initialize();
    if (result != returnvalue::OK) {
      return result;
    }
  }

  return returnvalue::OK;
}

ReturnValue_t TemperatureSensorsDummy::handleCommandMessage(CommandMessage* message) {
  return returnvalue::FAILED;
}

void TemperatureSensorsDummy::performControlOperation() {
  iteration++;
  value = sin(iteration / 80. * M_PI) * 10;

  ReturnValue_t result = max31865Set.read();
  if (result != returnvalue::OK) {
    sif::warning << "Failed to read temperature from MAX31865 dataset" << std::endl;
  }
  max31865Set.rtdValue = value - 5;
  max31865Set.temperatureCelcius = value;
  if ((iteration % 100) < 20) {
    max31865Set.setValidity(false, true);
  } else {
    max31865Set.setValidity(true, true);
  }
  max31865Set.commit();
}

ReturnValue_t TemperatureSensorsDummy::initializeLocalDataPool(
    localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) {
  localDataPoolMap.emplace(static_cast<lp_id_t>(MAX31865::PoolIds::RTD_VALUE),
                           new PoolEntry<float>({0}));
  localDataPoolMap.emplace(static_cast<lp_id_t>(MAX31865::PoolIds::TEMPERATURE_C),
                           new PoolEntry<float>({0}));
  localDataPoolMap.emplace(static_cast<lp_id_t>(MAX31865::PoolIds::LAST_FAULT_BYTE),
                           new PoolEntry<uint8_t>({0}));
  localDataPoolMap.emplace(static_cast<lp_id_t>(MAX31865::PoolIds::FAULT_BYTE),
                           new PoolEntry<uint8_t>({0}));

  return returnvalue::OK;
}

LocalPoolDataSetBase* TemperatureSensorsDummy::getDataSetHandle(sid_t sid) {
  sif::debug << "getHandle" << std::endl;
  switch (sid.ownerSetId) {
    case MAX31865::MAX31865_SET_ID:
      return &max31865Set;
    default:
      return nullptr;
  }
}

ReturnValue_t TemperatureSensorsDummy::checkModeCommand(Mode_t mode, Submode_t submode,
                                                        uint32_t* msToReachTheMode) {
  if (submode != SUBMODE_NONE) {
    return INVALID_SUBMODE;
  }
  if ((mode != MODE_OFF) && (mode != MODE_ON) && (mode != MODE_NORMAL)) {
    return INVALID_MODE;
  }
  return returnvalue::OK;
}