#ifndef __GOOSE_HW_H__
#define __GOOSE_HW_H__
#include "tc_system.h"
#include <openssl/ssl.h>

typedef struct PowerRequest
{
    uint16_t connect_id;
    uint16_t serialnumb;
    uint16_t type;
    uint16_t mode;
    float requestV;
    float requestI;
    uint16_t resv0;
    uint16_t resv1;
}PowerRequest_t;

typedef struct PowerReply
{
    uint16_t connect_id;
    uint16_t serialnumb;
    uint16_t type;
    uint16_t result;
    uint16_t mode;
    float requestV;
    float requestI;
    uint16_t resv0;
    uint16_t resv1;
}PowerReply_t;

typedef struct ShutdownRequest
{
    uint16_t connect_id;
    uint16_t serialnumb;
    uint16_t reason;
    uint16_t resv0;
    uint16_t resv1;
}ShutdownRequest_t;

typedef struct ShutdownReply
{
    uint16_t connect_id;
    uint16_t serialnumb;
    uint16_t reason;
    uint16_t result;
    uint16_t reject;
}ShutdownReply_t;

typedef enum goose_HW_State
{
    GHWS_HEARTBEAT=0,
    GHWS_POWER_REQUEST=1,
    GHWS_SHUTDOWN_REQUEST=2
}goose_HW_Stae_t;

typedef struct goose_HW
{
    pthread_mutex_t mutex;
    
    int fd;
    int state;
    int quit;

    int T0;
    int T1;
    int T_idx;
    int64_t T[5];

    const char* interfaceID;

    char* goID;
    char* goCBRef;
    char* dataSetRef;
    uint32_t confRev;
    uint32_t stNum;
    uint32_t sqNum;
    uint16_t timeAllowedToLive;
    bool needsCommission;
    bool simulation;
    struct timeval timestamp;

    uint8_t src_mac[6];
    uint8_t dst_mac[6];

    uint8_t tx_buff[1536];
    int tx_bytes;
    uint8_t rx_buff[1536];
    int rx_bytes;

    char goID_cache[128];
    char goCBRef_cache[128];
    char dataSetRef_cache[128];

    uint8_t HMAC[48];

    PowerReply_t power_reply;
    ShutdownReply_t shutdown_reply;

    PowerRequest_t power_request;
    ShutdownRequest_t shutdown_request;

    struct sockaddr_ll sll;
    socklen_t  slen;
} goose_HW_t;

uint16_t goose_HW_crc16(uint8_t* addr, uint16_t addrLength);
uint32_t goose_HW_crc32(uint8_t* addr, uint16_t addrLength);

int goose_HW_encode_TLV(uint8_t* buff, int index, uint8_t tag, uint32_t length, uint8_t* value);
int goose_HW_encode_PowerRequest(goose_HW_t* dev, uint8_t* buff, int index, PowerRequest_t* pdu);
int goose_HW_encode_ShuntdownRequest(goose_HW_t* dev, uint8_t* buff, int index, ShutdownRequest_t* pdu);
int goose_HW_encode_APDU(goose_HW_t* dev, uint8_t* buff, int index, int SetEntries, uint8_t* apdu, int length);
int goose_HW_encode_Eth8021Q(goose_HW_t * dev, uint8_t* buff, int index, uint16_t priority, uint16_t VLAN, uint16_t APPID, uint8_t* APDU, int length);

int goose_HW_decode_APDU(goose_HW_t* dev, uint8_t* buff, int length);

void goose_HW_PowerRequest(goose_HW_t * dev);
void goose_HW_ShuntdownRequest(goose_HW_t * dev);

int goose_HW_init(goose_HW_t * dev, const char* interfaceID, uint16_t connector_id);
void* goose_HW_loop(void * argv);
void goose_HW_exit(goose_HW_t * dev);

#endif//__GOOSE_HW_H__
