#pragma once
#include "Core.h"

constexpr uint16_t PROTOCOL_MAGIC = 0x4F43;
constexpr uint8_t PROTOCOL_VERSION = 12;

enum class MessageType : uint8_t {
  DISCOVER, DISCOVER_ACK, PREPARE, READY, START_STAGE, RESULT, ACK, ABORT,
  HEARTBEAT, HEARTBEAT_ACK, PROGRESS
};

const char *messageName(MessageType type);

#pragma pack(push, 1)
struct ProtocolPacket {
  uint16_t magic;
  uint8_t version;
  uint8_t type;
  uint32_t session;
  uint16_t stage;
  uint16_t stageCount;
  uint16_t sequence;
  uint32_t requestedHz;
  uint32_t requestedPulseNs;
  uint32_t actualHz;
  uint32_t actualPulseNs;
  uint32_t testTimeMs;
  uint16_t accuracyX100;
  uint8_t lightCode;
  uint8_t progressStep;
  uint8_t passed;
  uint8_t reason;
  uint32_t periods;
  uint32_t measuredHzX10;
  uint32_t measuredPulseNs;
  uint32_t minPeriodTicks;
  uint32_t maxPeriodTicks;
  uint16_t crc;
};
#pragma pack(pop)

static_assert(sizeof(ProtocolPacket) == 62, "Protocol layout changed");

uint16_t packetCrc(const ProtocolPacket &packet);
void finalizePacket(ProtocolPacket &packet);
bool validPacket(const ProtocolPacket &packet);
