#ifndef PACKETSTRUCTS_FILE
#define PACKETSTRUCTS_FILE

#include <stdint.h>
#include "stddef.h"
#define ROUTE_TYPE_MASK 0x03
#define PAYLOAD_TYPE_MASK 0x3C
#define PAYLOAD_VERSION_MASK 0xC0

#define DONT_RETRANSMIT_HEADER 0xFF

#define RESP_SERVER_LOGIN_OK 0

#define FIRMWARE_VER_LEVEL 1

#define PERM_ACL_ROLE_MASK 3  // lower 2 bits
#define PERM_ACL_GUEST 0
#define PERM_ACL_READ_ONLY 1
#define PERM_ACL_READ_WRITE 2
#define PERM_ACL_ADMIN 3

#define NODE_ENTRY_FAV_FLAG (1 << 0)


#define MAX_PATH_LEN 64


#define TXT_TYPE_PLAIN 0         // a plain text message
#define TXT_TYPE_CLI_DATA 1      // a CLI command
#define TXT_TYPE_SIGNED_PLAIN 2  // plain text, signed by sender

typedef enum RouteType {
    ROUTE_TYPE_TRANSPORT_FLOOD = 0x00,
    ROUTE_TYPE_FLOOD = 0x01,
    ROUTE_TYPE_DIRECT = 0x02,
    ROUTE_TYPE_TRANSPORT_DIRECT = 0x03,
} RouteType;

typedef enum PayloadType {
    PAYLOAD_TYPE_REQ = 0x00 << 2,
    PAYLOAD_TYPE_RESPONSE = 0x01 << 2,
    PAYLOAD_TYPE_TXT_MSG = 0x02 << 2,
    PAYLOAD_TYPE_ACK = 0x03 << 2,
    PAYLOAD_TYPE_ADVERT = 0x04 << 2,
    PAYLOAD_TYPE_GRP_TXT = 0x05 << 2,
    PAYLOAD_TYPE_GRP_DATA = 0x06 << 2,
    PAYLOAD_TYPE_ANON_REQ = 0x07 << 2,
    PAYLOAD_TYPE_PATH = 0x08 << 2,
    PAYLOAD_TYPE_TRACE = 0x09 << 2,
    PAYLOAD_TYPE_MULTIPART = 0x0A << 2,
    PAYLOAD_TYPE_CONTROL = 0x0B << 2,
    PAYLOAD_TYPE_RAW_CUSTOM = 0x0F << 2,
} PayloadType;

typedef struct DiscoverRequestPayload {
    uint8_t prefixOnly;
    uint8_t typeFilter;
    uint32_t tag;
    uint32_t since;
} DiscoverRequestPayload;

typedef struct DiscoverResponsePayload {
    uint8_t nodeType;
    int8_t snr;
    uint32_t tag;
    uint8_t pubkey[32];
    uint8_t pubkeyLen;
} DiscoverResponsePayload;

typedef struct AnonymousRequestPayload {
    uint8_t destinationHash;
    uint8_t pubKey[32];
    uint16_t cipherMAC;
    uint8_t payloadLen;
    uint8_t payload[149];
} AnonymousRequestPayload;

typedef enum PayloadVersion {
    PAYLOAD_VERSION_0 = 0 << 6,
    PAYLOAD_VERSION_1 = 1 << 6,
    PAYLOAD_VERSION_2 = 2 << 6,
    PAYLOAD_VERSION_3 = 3 << 6,
} PayloadVersion;

typedef struct Path {
    uint8_t pathLen;
    uint8_t path[MAX_PATH_LEN];
} Path;

typedef struct FrameStruct {
    uint8_t header;
    uint8_t transportCodes[4];
    Path path;
    size_t payloadLen;
    uint8_t payload[184];
} FrameStruct;

typedef enum RequestType {
    REQUEST_GET_STATS = 0x01,
    REQUEST_KEEPALIVE = 0x02,
    REQUEST_GET_TELEMETRY_DATA = 0x03,
    REQUEST_GET_MIN_MAX_AVG = 0x04,
    REQUEST_GET_ACCESS_LIST = 0x05,
} RequestType;

typedef struct Request {
    uint32_t timestamp;
    uint8_t requestType;
    uint8_t dataLen;
    uint8_t data[180];  // hopefully correct len
} Request;

typedef struct Response {
    uint32_t tag;       // sender timestamp
    uint8_t dataLen;
    uint8_t data[180];  // hopefully correct len
} Response;

typedef struct Node {
    uint8_t pubKey[32];
    char name[32];
    int32_t latitude;
    int32_t longitude;
    int32_t lastSeen;
    char flags;
} Node;

typedef struct {
    char name[32];
    unsigned char pubKey[32];
    unsigned char secret[32];

    int32_t gps_latitude;
    int32_t gps_longitude;

    Path path;

    uint8_t flags;
    uint8_t type;

    uint8_t authenticated;

    uint32_t last_seen_rt;  // remote timestamp
    uint32_t last_seen_lt;  // local timestamp

    uint32_t sync_timestamp;
} NodeEntry;

typedef struct EncryptedPayloadStruct {
    uint8_t destinationHash;
    uint8_t sourceHash;
    uint16_t cipherMAC;
    uint8_t payloadLen;
    uint8_t payload[180];
    uint8_t type;
    NodeEntry *remNode;
    const Path *path;
    const FrameStruct *origFrame;
} EncryptedPayloadStruct;

typedef enum NodeType {
    NODE_TYPE_CHAT_NODE = 1,
    NODE_TYPE_REPEATER = 2,
    NODE_TYPE_ROOM_SERVER = 3,
    NODE_TYPE_SENSOR = 4
} NodeType;

typedef enum ControlDataFlags {
    CONTROL_DATA_FLAG_TYPE_NODE_DISCOVER_REQ = 0x80,
    CONTROL_DATA_FLAG_DISCOVER_RESP = 0x90
} ControlDataFlags;

typedef enum AdvertisementPayloadFlags {
    ADVERTISEMENT_FLAG_IS_CHAT_NODE = 0x01,
    ADVERTISEMENT_FLAG_IS_REAPEATER = 0x02,
    ADVERTISEMENT_FLAG_IS_ROOM_SERVER = 0x03,
    ADVERTISEMENT_FLAG_IS_SENSOR = 0x04,
    ADVERTISEMENT_FLAG_HAS_LOCATION = 0x10,
    ADVERTISEMENT_FLAG_RFU1 = 0x20,
    ADVERTISEMENT_FLAG_RFU2 = 0x40,
    ADVERTISEMENT_FLAG_HAS_NAME = 0x80,
} AdvertisementPayloadFlags;

typedef struct AdvertisementPayload {
    uint8_t pubKey[32];
    int32_t timestamp;
    uint8_t signature[64];
    uint8_t valid;
    uint8_t dataFlags;
    int32_t latitude;
    int32_t longitude;
    int16_t rfu1;
    int16_t rfu2;
    char nodeName[32];

} AdvertisementPayload;

typedef struct Extra {
    uint8_t type;
    uint8_t dataLen;
    uint8_t data[180];  // hopefully long enough
} Extra;

typedef struct ReturnedPathPayload {
    Path path;
    Extra extra;
} ReturnedPathPayload;

typedef struct PlainTextMessagePayload {
    uint32_t timestamp;
    uint8_t textType;
    uint8_t attempt;
    uint8_t message[180];  // hopefully long enough
} PlainTextMessagePayload;

typedef struct GroupTextMessage {
    uint8_t channelHash;
    uint8_t keyIndex;
    int32_t timestamp;
    uint8_t flags;
    uint8_t text[190];
} GroupTextMessage;

typedef struct RepeaterStats {
    uint16_t millivolts;
    uint16_t txQueueLength;
    int16_t noiseFloor;
    int16_t lastRSSI;
    uint32_t packetsReceivedCount;
    uint32_t packetsSentCount;
    uint32_t totalAirTimeSeconds;
    uint32_t totalUpTimeSeconds;
    uint32_t sentFloodCount, sentDirectCount;
    uint32_t receivedFloodCount, receivedDirectCount;
    uint16_t err_events;  // was 'n_full_events'
    int16_t lastSNR;      // x 4
    uint16_t n_direct_dups, n_flood_dups;
    uint32_t total_rx_air_time_secs;
} RepeaterStats;

typedef struct Channel {
    char name[32];
    uint8_t key[16];
    uint8_t hash;
    int32_t timestamp;
} Channel;

#endif
