#pragma once

#include <cstddef>
#include <cstdint>
#include <string>

#include "SdCardManager.h"
#include "definitions.h"

namespace xsc {

enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };

}  // namespace xsc

struct RebootFile {
  static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;

  bool enabled = true;
  size_t maxCount = DEFAULT_MAX_BOOT_CNT;
  uint32_t img00Cnt = 0;
  uint32_t img01Cnt = 0;
  uint32_t img10Cnt = 0;
  uint32_t img11Cnt = 0;
  bool img00Lock = false;
  bool img01Lock = false;
  bool img10Lock = false;
  bool img11Lock = false;
  uint32_t* relevantBootCnt = &img00Cnt;
  bool bootFlag = false;
  xsc::Chip lastChip = xsc::Chip::CHIP_0;
  xsc::Copy lastCopy = xsc::Copy::COPY_0;
  xsc::Chip mechanismNextChip = xsc::Chip::NO_CHIP;
  xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
};

class SdCardManager;

class CoreController {
 public:
  static constexpr char REBOOT_FILE[] = "/conf/reboot.txt";
  //! [EXPORT] : [COMMENT] The reboot mechanism was triggered.
  //! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy,
  //! P2: Each byte is the respective reboot count for the slots
  static constexpr Event REBOOT_MECHANISM_TRIGGERED = 1;
  static xsc::Chip CURRENT_CHIP;
  static xsc::Copy CURRENT_COPY;

  static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
  static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
  static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
  static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8;

  CoreController();

  static void setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy);
  ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
                              const uint8_t* data, size_t size);
  void performRebootFileHandling(bool recreateFile);
  void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
                                 xsc::Copy& tgtCopy);
  void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
  void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
  bool parseRebootFile(std::string path, RebootFile& file);
  void rewriteRebootFile(RebootFile file);

 private:
  struct SdFsmParams {
    sd::SdCard active = sd::SdCard::NONE;
    sd::SdState activeState = sd::SdState::OFF;
    sd::SdCard other = sd::SdCard::NONE;
    sd::SdState otherState = sd::SdState::OFF;
  } sdInfo;

  SdCardManager* sdcMan = nullptr;
  RebootFile rebootFile = {};
  bool doPerformRebootFileHandling = true;
};