#ifndef __OCPP16_CLIENT_H__
#define __OCPP16_CLIENT_H__
#include "msystem.h"
#include "mthread.h"
#include "mtimer.h"
#include "mwebsocket.h"
#include "ccu_config.h"
#include "ocpp16.h"
#include "cJSON.h"

#define OCPP_PTHREAD_COND_TIMEOUT  1
#define OCPP_SEMPARE_TIMEOUT_MS    3000

typedef struct ocpp_client
{
    int fd;
    int debug;
    char online[32];
    int connected;
    int handshaked;
    struct sockaddr_in selfaddr;
    struct sockaddr_in peeraddr;
    char self_ip[128];
    short self_port;
    short peer_port;
    char peer_ip[128];

    short server_port;
    char path[128];
    char server_ip[64];
    char Sec_WebSocket_Key[128];
    char Sec_WebSocket_Accept[128];
    char Sec_WebSocket_Protocol[128];

    uint8_t txbuff[4096];
    uint8_t rxbuff[4096];
    uint8_t txstream[4096+32];
    uint8_t rxstream[4096+32];

    int txbyte;
    int rxbyte;

    uint8_t txtype;
    uint8_t txmask;

    uint8_t rxtype;
    uint8_t rxmask;

    /************************************/
    int quit;
    int fp[2];
    
    uint8_t pipe_rxbuff[4096];
    size_t  pipe_rxbyte;

    sem_t rxroot_sem;
    pthread_cond_t  cond_rx;
    pthread_mutex_t mutex_rx;
    pthread_mutex_t mutex_tx;

    mthread_t  threadRx;
    mthread_t  threadTx;

    /************************************/
    ocpp16_config_t *config;
    void* ccu;

    int boot_notification_readay;
    int ocpp16_offlineChargingRecords_uploaded;

    int trigger_flag;
    int HeartbeatInterval;
    time_t HeartbeatTime;

    struct
    {
        char location[255];     // Required
        int retries;			// Optional
        int retryInterval;		// Optional
        time_t startTime;		// Optional
        time_t stopTime;		// Optional
    } diagnosticsReq;
    int need_diagnostics;

    struct
    {
        char location[255];         // Required.
        time_t retrieveDate;        // Required.
        int retries;			    // Optional.
        int retryInterval;		    // Optional.
    } updateFirmware;
    int need_updatefirmware;
    int need_reset;
}ocpp_client_t;

typedef struct ocpp_method
{
    const char* name;
    int (*callback)(ocpp_client_t* dev, uint32_t msgType, CidString37_t msgUUID, cJSON* payload);
}ocpp_method_t;

extern ocpp_client_t ocpp0;
extern ocpp_client_t ocpp1;

void ocpp16_client_init(ocpp_client_t* dev, ocpp16_config_t *ocpp_config);
void ocpp16_client_exit(ocpp_client_t* dev);

int ocpp16_client_online(ocpp_client_t* dev);

int ocpp16_Authorize_request(ocpp_client_t* dev, AuthorizeReq_t* req, AuthorizeConf_t* conf);

int ocpp16_BootNotification_request(ocpp_client_t* dev, BootNotificationReq_t* req, BootNotificationConf_t* conf);

int ocpp16_DataTransfer_request(ocpp_client_t* dev, DataTransferReq_t* req, DataTransferConf_t* conf);

int ocpp16_DiagnosticsStatusNotification_request(ocpp_client_t* dev, DiagnosticsStatus_t status);

int ocpp16_FirmwareStatusNotification_request(ocpp_client_t* dev, FirmwareStatus_t status);

int ocpp16_Heartbeat_request(ocpp_client_t* dev, HeartbeatReq_t* req, HeartbeatConf_t* conf);

int ocpp16_MeterValues_request(ocpp_client_t* dev, MeterValuesReq_t* req);

int ocpp16_StartTransaction_request(ocpp_client_t* dev, StartTransactionReq_t* req, StartTransactionConf_t* conf);

int ocpp16_StatusNotification_request(ocpp_client_t* dev, StatusNotificationReq_t* req);

int ocpp16_StopTransaction_request(ocpp_client_t* dev, StopTransactionReq_t* req, StopTransactionConf_t* conf);

//--------------------------------------------------------------------------------------------------------------

int ocpp16_CancelReservation_confirm(ocpp_client_t* dev, CancelReservationReq_t* req, CancelReservationConf_t* conf);

int ocpp16_ChangeAvailability_confirm(ocpp_client_t* dev, ChangeAvailabilityReq_t* req, ChangeAvailabilityConf_t* conf);

int ocpp16_ChangeConfiguration_confirm(ocpp_client_t* dev, ChangeConfigurationReq_t* req, ChangeConfigurationConf_t* conf);

int ocpp16_ClearCache_confirm(ocpp_client_t* dev, ClearCacheReq_t* req, ClearCacheConf_t* conf);

int ocpp16_ClearChargingProfile_confirm(ocpp_client_t* dev, ClearChargingProfileReq_t* req, ClearChargingProfileConf_t* conf);

int ocpp16_DataTransfer_confirm(ocpp_client_t* dev, DataTransferReq_t* req, DataTransferConf_t* conf);

int ocpp16_GetCompositeSchedule_confirm(ocpp_client_t* dev, GetCompositeScheduleReq_t* req, GetCompositeScheduleConf_t* conf);

int ocpp16_GetConfiguration_confirm(ocpp_client_t* dev, GetConfigurationReq_t* req, GetConfigurationConf_t* conf);

int ocpp16_GetDiagnostics_confirm(ocpp_client_t* dev, GetDiagnosticsReq_t* req, GetDiagnosticsConf_t* conf);

int ocpp16_GetLocalListVersion_confirm(ocpp_client_t* dev, GetLocalListVersionReq_t* req, GetLocalListVersionConf_t* conf);

int ocpp16_RemoteStartTransaction_confirm(ocpp_client_t* dev, RemoteStartTransactionReq_t* req, RemoteStartTransactionConf_t* conf);

int ocpp16_RemoteStopTransaction_confirm(ocpp_client_t* dev, RemoteStopTransactionReq_t* req, RemoteStopTransactionConf_t* conf);

int ocpp16_ReserveNow_confirm(ocpp_client_t* dev, ReserveNowReq_t* req, ReserveNowConf_t* conf);

int ocpp16_Reset_confirm(ocpp_client_t* dev, ResetReq_t* req, ResetConf_t* conf);

int ocpp16_SendLocalList_confirm(ocpp_client_t* dev, SendLocalListReq_t* req, SendLocalListConf_t* conf);

int ocpp16_SetChargingProfile_confirm(ocpp_client_t* dev, SetChargingProfileReq_t* req, SetChargingProfileConf_t* conf);

int ocpp16_TriggerMessage_confirm(ocpp_client_t* dev, TriggerMessageReq_t* req, TriggerMessageConf_t* conf);

int ocpp16_UnlockConnector_confirm(ocpp_client_t* dev, UnlockConnectorReq_t* req, UnlockConnectorConf_t* conf);

int ocpp16_UpdateFirmware_confirm(ocpp_client_t* dev, UpdateFirmwareReq_t* req, UpdateFirmwareConf_t* conf);

#endif//__OCPP16_CLIENT_H__
