#ifndef __MQTT_UTILS_H__
#define __MQTT_UTILS_H__

#ifdef  __cplusplus
extern "C" {
#endif

#include <semaphore.h>

#include "MQTTAsync.h"
#include "MQTTClientPersistence.h"
#include "json_utils.h"

#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#ifndef container_of
/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:	the pointer to the member.
 * @type:	the type of the container struct this is embedded in.
 * @member:	the name of the member within the struct.
 *
 */
#define container_of(ptr, type, member) ({			\
        const typeof(((type *)0)->member) * __mptr = (ptr);	\
        (type *)((char *)__mptr - offsetof(type, member)); })
#endif

typedef struct
{
	MQTTAsync client;
	MQTTAsync_responseOptions sub_opts;
	MQTTAsync_responseOptions pub_opts;

	sem_t sem_connect;			//mqtt connect semaphore

	/* MQTT options */
	enum MQTTASYNC_TRACE_LEVELS tracelevel;
	char host[64];		//mqtt broker ip
	int port;			//mqtt broker port
	char username[64];	//user name
	char password[64];	//user password
	int keepalive;		//mqtt keepalive
	int retain;			//mqtt retain
	char clientid[64];	//mqtt client id
	char productcode[64];	//mqtt productcode
	int MQTTVersion;

	/* will options */
	char* will_topic;
	char* will_payload;
	int will_qos;
	int will_retain;

	/* TLS options */
	char protocol[64];	//tcp ssl wss
	int insecure;
	char* capath;
	char* cert;
	char* cafile;
	char* key;
	char* keypass;
	char* ciphers;
}mqtt_utils_t;

extern mqtt_utils_t mqtt_config;
extern void PutDataIntoMQueue(char *payload);

typedef struct{
    char msg_messageId[32];
    char msg_fwVersion[32];
    char msg_fwUrl[256];
    int msg_taskId;
}mqtt_parm_download_t;

typedef struct
{
    char msg_deviceId[32];
    char msg_messageId[64];
    char msg_key[32];
    char msg_devName[32];
    char msg_taskId[32];
    char msg_groupNo[4];
    char msg_time[32];
    char msg_ext1[32];
    char msg_ext2[32];
    char msg_sn[7];
    int msg_opNumber;
    int msg_action;
    int msg_color;
    int msg_duration;
}mqtt_parm_t;

extern void mqtt_net_failure(int *failure_times);
extern int mqtt_utils_init(mqtt_utils_t *mqtt_utils);
extern int get_trace_level_by_name(char *name);
extern int mqtt_utils_subscribe(mqtt_utils_t *mqtt_utils, char *topic, int qos);
extern int mqtt_utils_publish(mqtt_utils_t *mqtt_utils, char *topic, int qos, const char *data,  int datalen);
extern int mqtt_utils_uninit(mqtt_utils_t *mqtt_utils);
void mqtt_server_reply(char *sn,char *msg_id,json_object *functions);
void mqtt_server_events_report(char *sn,char *msg_id,json_object *events);
#ifdef  __cplusplus
}
#endif

#endif
