#ifndef MISSION_ARDUINOCOMMINTERFACE_H_
#define MISSION_ARDUINOCOMMINTERFACE_H_

#include <fsfw/container/FixedMap.h>
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/returnvalues/returnvalue.h>

#include <cstdint>
#include <map>

#ifdef WIN32
#include <windows.h>
#endif

// Forward declaration, so users don't peek
class ArduinoCookie;

class ArduinoComIF : public SystemObject, public DeviceCommunicationIF {
 public:
  static const uint8_t MAX_NUMBER_OF_SPI_DEVICES = 8;
  static const uint8_t MAX_PACKET_SIZE = 64;

  static const uint8_t COMMAND_INVALID = -1;
  static const uint8_t COMMAND_SPI = 1;

  ArduinoComIF(object_id_t setObjectId, bool promptComIF = false,
               const char *serialDevice = nullptr);
  void setBaudrate(uint32_t baudRate);

  virtual ~ArduinoComIF();

  /** DeviceCommunicationIF overrides */
  virtual ReturnValue_t initializeInterface(CookieIF *cookie) override;
  virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData,
                                    size_t sendLen) override;
  virtual ReturnValue_t getSendSuccess(CookieIF *cookie) override;
  virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
  virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
                                            size_t *size) override;

 private:
#ifdef LINUX
#elif WIN32
  HANDLE hCom = INVALID_HANDLE_VALUE;
#endif
  // remembering if the initialization in the ctor worked
  // if not, all calls are disabled
  bool initialized = false;
  int serialPort = 0;
  // Default baud rate is 9600 for now.
  uint32_t baudRate = 9600;

  // used to know where to put the data if a reply is received
  std::map<uint8_t, ArduinoCookie> spiMap;

  SimpleRingBuffer rxBuffer;

  ReturnValue_t sendMessage(uint8_t command, uint8_t address, const uint8_t *data, size_t dataLen);
  void handleSerialPortRx();

  void handlePacket(uint8_t *packet, size_t packetLen);
};

#endif /* MISSION_ARDUINOCOMMINTERFACE_H_ */