#ifndef MISSION_SYSTEM_EIVESYSTEM_H_
#define MISSION_SYSTEM_EIVESYSTEM_H_

#include <fsfw/action/HasActionsIF.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/subsystem/Subsystem.h>

#include <atomic>

class EiveSystem : public Subsystem, public HasActionsIF {
 public:
  static constexpr uint8_t FRAME_DIRTY_COM_REBOOT_LIMIT = 4;

  static constexpr ActionId_t EXECUTE_I2C_REBOOT = 10;

  EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables,
             std::atomic_uint16_t& i2cErrors);

  void setI2cRecoveryParams(PowerSwitchIF* pwrSwitcher);

  [[nodiscard]] MessageQueueId_t getCommandQueue() const override;

 private:
  enum class I2cRebootState {
    NONE,
    SYSTEM_MODE_BOOT,
    SWITCH_3V3_STACK_OFF_AND_BATT_REBOOT,
    WAIT_CYCLE,
    SWITCH_3V3_STACK_ON,
    SYSTEM_MODE_SAFE
  } i2cRebootState = I2cRebootState::NONE;

  MessageQueueIF* eventQueue = nullptr;
  bool performSafeRecovery = false;
  bool performI2cReboot = false;
  bool alreadyTriedI2cRecovery = false;

  uint8_t frameDirtyErrorCounter = 0;
  Countdown frameDirtyCheckCd = Countdown(10000);
  // If the PDEC reset was already attempted in the last 2 minutes, there is a high chance that
  // only a full reboot will fix the issue.
  Countdown ptmeResetWasAttemptedCd = Countdown(120000);
  bool ptmeResetWasAttempted = false;

  ActionHelper actionHelper;
  PowerSwitchIF* powerSwitcher = nullptr;
  std::atomic_uint16_t& i2cErrors;

  MessageQueueId_t pdecHandlerQueueId = MessageQueueIF::NO_QUEUE;

  MessageQueueId_t bpxBattQueueId = MessageQueueIF::NO_QUEUE;
  MessageQueueId_t coreCtrlQueueId = MessageQueueIF::NO_QUEUE;
  MessageQueueId_t actionCommandedBy = MessageQueueIF::NO_QUEUE;
  Countdown i2cRebootHandlingCountdown = Countdown(10000);
  //  After 1 minute, clear the flag to avoid full reboots on I2C issues.
  Countdown i2cRecoveryClearCountdown = Countdown(60000);
  ReturnValue_t initialize() override;
  void performChildOperation() override;
  void announceMode(bool recursive) override;

  ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
                              const uint8_t* data, size_t size) override;
  ReturnValue_t handleCommandMessage(CommandMessage* message) override;

  ReturnValue_t sendFullRebootCommand();

  void pdecRecoveryLogic();

  void i2cRecoveryLogic();
  void handleEventMessages();
  void commandSelfToSafe();
  void commonI2cRecoverySequenceFinish();
};

#endif /* MISSION_SYSTEM_EIVESYSTEM_H_ */