#ifndef __TANGO_CACHE_CLIENT_IN_H__
#define __TANGO_CACHE_CLIENT_IN_H__

#include <curl/curl.h>
#include <sys/queue.h>

#include <event2/event.h>  
#include <event.h>

#include <MESA/wiredLB.h>
#include "tango_cache_client.h"

#define RESPONSE_HDR_EXPIRES 1
#define RESPONSE_HDR_LAST_MOD 2
#define RESPONSE_HDR_ALL	3

enum CACHE_REQUEST_METHOD
{
	CACHE_REQUEST_GET=0,
	CACHE_REQUEST_PUT,
	CACHE_REQUEST_DELETE,
	CACHE_REQUEST_DELETE_MUL,
};

enum GET_OBJECT_STATE
{
	GET_STATE_START=0,
	GET_STATE_DELETE,
	GET_STATE_END,
};

enum PUT_OBJECT_STATE
{
	PUT_STATE_START=0,
	PUT_STATE_WAIT_START,
	PUT_STATE_PART,
	PUT_STATE_END,
	PUT_STATE_CANCEL,
};

struct easy_string
{
	char* buff;
	size_t len;
	size_t size;
};

struct tango_cache_instance
{
	char minio_iplist[4096];
	char bucketname[256];
	char wiredlb_topic[64];
	char wiredlb_group[64];
	char wiredlb_datacenter[64];
	u_int32_t minio_port;
	u_int32_t wiredlb_override;
	u_int16_t wiredlb_ha_port;
	u_int32_t hash_object_key;
	struct event_base* evbase;
	struct event timer_event;
	struct cache_statistics statistic;
	CURLM *multi_hd;
	void *runtime_log;
	WLB_handle_t wiredlb;
	time_t relative_ttl; //缓存的相对有效期
	u_int64_t cache_limit_size;
	long max_cnn_host;
	u_int32_t upload_block_size; //minio分段上传块的最小长度
	enum CACHE_ERR_CODE error_code;
};

struct multipart_etag_list
{
	char *etag;
	u_int32_t part_number;
	TAILQ_ENTRY(multipart_etag_list) node;
};

struct cache_ctx_data_get
{
	time_t max_age;
	time_t min_fresh;
	time_t expires;
	time_t last_modify;
	u_int32_t need_hdrs;
	enum GET_OBJECT_STATE state;
	struct easy_string response_tag;
	struct tango_cache_result result;
};

struct cache_ctx_data_put
{
	struct evbuffer *evbuf;
	size_t upload_length;
	size_t upload_offset;
	char *uploadID;
	char *combine_xml;
	TAILQ_HEAD(__etag_list_head, multipart_etag_list) etag_head;
	enum PUT_OBJECT_STATE state;
	u_int32_t part_index; //宏RESPONSE_HDR_
	bool close_state; //主动被调用关闭
};

struct cache_ctx_multi_delete
{
	u_int32_t succ_num;
	u_int32_t fail_num;
};

struct tango_cache_ctx
{
	CURL *curl;
	struct curl_slist *headers;
	struct future* future;
	char error[CURL_ERROR_SIZE];	
	char object_key[256];
	char hostaddr[48];

	enum CACHE_REQUEST_METHOD method;
	enum CACHE_ERR_CODE error_code;
	struct easy_string response;

	bool fail_state;
	long res_code;
	
	union{
		struct cache_ctx_data_put put;
		struct cache_ctx_data_get get;
		struct cache_ctx_multi_delete del;
	};
	struct tango_cache_instance *instance;
};

struct curl_socket_data
{
	struct event sock_event;
};

void caculate_sha256(const char *data, unsigned long len, char *result, u_int32_t size);

void easy_string_savedata(struct easy_string *estr, const char *data, size_t len);
void easy_string_destroy(struct easy_string *estr);

void tango_cache_ctx_destroy(struct tango_cache_ctx *ctx);
void tango_cache_set_fail_state(struct tango_cache_ctx *ctx, enum CACHE_ERR_CODE error_code);
const char *tango_cache_get_errstring(const struct tango_cache_ctx *ctx);

struct tango_cache_ctx *tango_cache_update_prepare(struct tango_cache_instance *instance, struct future* f, struct tango_cache_meta_put *meta);
struct tango_cache_ctx *tango_cache_fetch_prepare(struct tango_cache_instance *instance, struct future* f, struct tango_cache_meta_get *meta);
struct tango_cache_ctx *tango_cache_delete_prepare(struct tango_cache_instance *instance, struct future* f, const char *objkey);

#endif

