#include <Arduino.h>
#pragma pack(push, 1)

#include "../../tag_types.h"

struct espBlockRequest {
    uint8_t checksum;
    uint64_t ver;
    uint8_t blockId;
    uint8_t src[8];
} __packed;

struct espXferComplete {
    uint8_t checksum;
    uint8_t src[8];
} __packed;

struct espSetChannelPower {
    uint8_t checksum;
    uint8_t channel;
    uint8_t power;
} __packed;

struct blockData {
    uint16_t size;
    uint16_t checksum;
    uint8_t data[];
} __packed;

struct AvailDataReq {
    uint8_t checksum;
    uint8_t lastPacketLQI;
    int8_t lastPacketRSSI;
    int8_t temperature;
    uint16_t batteryMv;
    uint8_t hwType;
    uint8_t wakeupReason;
    uint8_t capabilities;
} __packed;

struct espAvailDataReq {
    uint8_t checksum;
    uint8_t src[8];
    struct AvailDataReq adr;
} __packed;

#define EPD_LUT_DEFAULT 0
#define EPD_LUT_NO_REPEATS 1
#define EPD_LUT_FAST_NO_REDS 2
#define EPD_LUT_FAST 3
#define EPD_LUT_OTA 0x10

struct AvailDataInfo {
    uint8_t checksum;
    uint64_t dataVer;              // MD5 of potential traffic
    uint32_t dataSize;              
    uint8_t dataType;          // allows for 16 different datatypes
    uint8_t dataTypeArgument;  // extra specification or instruction for the tag (LUT to be used for drawing image)
    uint16_t nextCheckIn;          // when should the tag check-in again? Measured in minutes
} __packed;

struct pendingData {
    struct AvailDataInfo availdatainfo;
    uint16_t attemptsLeft;
    uint8_t targetMac[8];
} __packed;

#define BLOCK_DATA_SIZE 4096
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)

#define PKT_AVAIL_DATA_REQ 0xE5
#define PKT_AVAIL_DATA_INFO 0xE6
#define PKT_XFER_COMPLETE 0xEA
#define PKT_XFER_TIMEOUT 0xED
#define PKT_CANCEL_XFER 0xEC
#define PKT_APLIST_REQ 0x80
#define PKT_APLIST_REPLY 0x81
#define PKT_TAGINFO 0x82

struct APlist {
    uint32_t src;
    char alias[32];
    uint8_t channelId;
    uint8_t tagCount;
    uint16_t version;
} __packed;

#define SYNC_NOSYNC 0
#define SYNC_USERCFG 1
#define SYNC_TAGSTATUS 2
#define SYNC_DELETE 3
#define SYNC_VERSION 0xAA00

struct TagInfo {
    uint16_t structVersion = SYNC_VERSION;
    uint8_t mac[8];
    uint8_t syncMode;
    char alias[32];
    uint32_t lastseen;
    uint32_t nextupdate;
    bool pending;
    uint32_t expectedNextCheckin;
    uint8_t hwType;
    uint8_t wakeupReason;
    uint8_t capabilities;
    uint16_t pendingIdle;
    uint8_t contentMode;
} __packed;

#pragma pack(pop)