#ifndef LIBTTN_PACKET_H
#define LIBTTN_PACKET_H
/****************************************************************************************************************/

#include "ttn/lnk/struct.h"

#define TTN_PACKET_PREFIX    2   // Each message header is 2 bytes
#define TTN_PACKET_SUFFIX    2   // PAC has additionally 2 bytes of checksum

#define TTN_PACKET_OVERHEAD  4   // Prefix + Suffix

// Alltogether now
#define TTN_OP_ITT           1  // Invitation To Transmit
#define TTN_OP_PAC           2  // Packet
#define TTN_OP_ACK           3  // Acknowledge
#define TTN_OP_NAK           4  // Negative Acknowledge
#define TTN_OP_CMG           5  // Chain management

// Chain management sub-opcode
#define TTN_MGOP_PROBE       0  // Probe for new devices                            mac, bits
#define TTN_MGOP_RESPONSE    1  // Probed device responds                           mac, ver, rev, feat
#define TTN_MGOP_ASSIGN      2  // Probed device gets linked into the chain         mac, nid
#define TTN_MGOP_QUERY       3  // Query a set of devices                           bitmap
#define TTN_MGOP_BUZZ        4  // Flash LEDs and make noise                        -

// Packet
typedef struct ttn_packet_t {

  uint8_t did:5;
  uint8_t op:3;

  uint8_t sid:5;
  uint8_t reserved:2;
  uint8_t rtr:1;

  union {
    uint8_t crc8;

    struct {
      uint8_t info[TTN_CONFIG_MAX_PAYLOAD_SIZE];
      uint8_t crc16[2];
    } __attribute__((packed)) pac;

    struct {
      uint8_t nid;
      uint8_t crc8;
    } __attribute__((packed)) nid;

    struct {
      uint8_t mgop;
      uint8_t bits;
      uint8_t mac[6];
      uint8_t crc16[2];
    } __attribute__((packed)) mgop_probe;

    struct {
      uint8_t mgop;
      uint8_t mac[6];
      uint8_t version;
      uint8_t revision;
      uint8_t feat[3];
      uint8_t crc16[2];
    } __attribute__((packed)) mgop_response;

    struct {
      uint8_t mgop;
      uint8_t next_tid;
      uint8_t mac[6];
      uint8_t crc16[2];
    } __attribute__((packed)) mgop_assign;

    struct {
      uint8_t mgop;
      uint8_t crc16[2];
    } __attribute__((packed)) mgop_plain;

  };

} __attribute__((packed)) ttn_packet_t;

#define MGOP_PACKET_SIZE(type) (offsetof(ttn_packet_t, type.crc16) + 2)

/****************************************************************************************************************/

#if TTN_PACKET_PREFIX != 2
#error PKB structure was aligned for a 2 byte TTN packet prefix
#error  The ethernet link layer header is 14 bytes, then followed by the network layer.
#error  By padding it with two bytes in front of it, the network layer aligns with 32bits.
#error  These two bytes match the size of TTN message header, which is also two bytes.
#error  If this is not the case, a lot of assumptions will break.
#endif

/****************************************************************************************************************/
#endif
