



#include "kvstore.h"
#include "kvs_rw_tools.h"

#if ENABLE_ARRAY
extern kvs_array_t global_array;
#endif

#if ENABLE_RBTREE
extern kvs_rbtree_t global_rbtree;
#endif

#if ENABLE_HASH
extern kvs_hash_t global_hash;
#endif

void *kvs_malloc(size_t size) {
	return malloc(size);
}

void kvs_free(void *ptr) {
	return free(ptr);
}


const char *command[] = {
	"SET", "GET", "DEL", "MOD", "EXIST",
	"RSET", "RGET", "RDEL", "RMOD", "REXIST",
	"HSET", "HGET", "HDEL", "HMOD", "HEXIST"
};

enum {
	KVS_CMD_START = 0,
	// array
	KVS_CMD_SET = KVS_CMD_START,
	KVS_CMD_GET,
	KVS_CMD_DEL,
	KVS_CMD_MOD,
	KVS_CMD_EXIST,
	// rbtree
	KVS_CMD_RSET,
	KVS_CMD_RGET,
	KVS_CMD_RDEL,
	KVS_CMD_RMOD,
	KVS_CMD_REXIST,
	// hash
	KVS_CMD_HSET,
	KVS_CMD_HGET,
	KVS_CMD_HDEL,
	KVS_CMD_HMOD,
	KVS_CMD_HEXIST,
	
	KVS_CMD_COUNT,
};



const char *response[] = {

};


int kvs_split_token(char *msg, char *tokens[]) {

	if (msg == NULL || tokens == NULL) return -1;

	int idx = 0;
	char *token = strtok(msg, " ");
	
	while (token != NULL) {
		//printf("idx: %d, %s\n", idx, token);
		
		tokens[idx ++] = token;
		token = strtok(NULL, " ");
	}

	return idx;
}


// SET Key Value
// tokens[0] : SET
// tokens[1] : Key
// tokens[2] : Value

int kvs_filter_protocol(char **tokens, int count, char *response) {

	if (tokens[0] == NULL || count == 0 || response == NULL) return -1;

	int cmd = KVS_CMD_START;
	for (cmd = KVS_CMD_START;cmd < KVS_CMD_COUNT;cmd ++) {
		if (strcmp(tokens[0], command[cmd]) == 0) {
			break;
		} 
	}

	int length = 0;
	int ret = 0;
	char *key = tokens[1];
	char *value = tokens[2];

	switch(cmd) {
#if ENABLE_ARRAY
	case KVS_CMD_SET:
		ret = kvs_array_set(&global_array ,key, value);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "EXIST\r\n");
		} 
		
		break;
	case KVS_CMD_GET: {
		char *result = kvs_array_get(&global_array, key);
		if (result == NULL) {
			length = sprintf(response, "NO EXIST\r\n");
		} else {
			length = sprintf(response, "%s\r\n", result);
		}
		break;
	}
	case KVS_CMD_DEL:
		ret = kvs_array_del(&global_array ,key);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
 		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
	case KVS_CMD_MOD:
		ret = kvs_array_mod(&global_array ,key, value);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
 		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
	case KVS_CMD_EXIST:
		ret = kvs_array_exist(&global_array ,key);
		if (ret == 0) {
			length = sprintf(response, "EXIST\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
#endif
	// rbtree
#if ENABLE_RBTREE
	case KVS_CMD_RSET:
		ret = kvs_rbtree_set(&global_rbtree ,key, value);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "EXIST\r\n");
		} 
		
		break;
	case KVS_CMD_RGET: {
		char *result = kvs_rbtree_get(&global_rbtree, key);
		if (result == NULL) {
			length = sprintf(response, "NO EXIST\r\n");
		} else {
			length = sprintf(response, "%s\r\n", result);
		}
		break;
	}
	case KVS_CMD_RDEL:
		ret = kvs_rbtree_del(&global_rbtree ,key);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
 		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
	case KVS_CMD_RMOD:
		ret = kvs_rbtree_mod(&global_rbtree ,key, value);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
 		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
	case KVS_CMD_REXIST:
		ret = kvs_rbtree_exist(&global_rbtree ,key);
		if (ret == 0) {
			length = sprintf(response, "EXIST\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
#endif
#if ENABLE_HASH
	case KVS_CMD_HSET:
		ret = kvs_hash_set(&global_hash ,key, value);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "EXIST\r\n");
		} 
		
		break;
	case KVS_CMD_HGET: {
		char *result = kvs_hash_get(&global_hash, key);
		if (result == NULL) {
			length = sprintf(response, "NO EXIST\r\n");
		} else {
			length = sprintf(response, "%s\r\n", result);
		}
		break;
	}
	case KVS_CMD_HDEL:
		ret = kvs_hash_del(&global_hash ,key);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
 		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
	case KVS_CMD_HMOD:
		ret = kvs_hash_mod(&global_hash ,key, value);
		if (ret < 0) {
			length = sprintf(response, "ERROR\r\n");
 		} else if (ret == 0) {
			length = sprintf(response, "OK\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
	case KVS_CMD_HEXIST:
		ret = kvs_hash_exist(&global_hash ,key);
		if (ret == 0) {
			length = sprintf(response, "EXIST\r\n");
		} else {
			length = sprintf(response, "NO EXIST\r\n");
		}
		break;
#endif

	default: 
		assert(0);
	}

	return length;
}

/**
 * 输入：op argc argv
 * 输出 status
 */
 void kvs_exec_one_op(uint8_t op, uint32_t argc, char **argv,
                            uint8_t *status_out,
                            const char **data_out, uint32_t *dlen_out) {
	*status_out = KVS_STATUS_ERROR;
	*data_out = NULL;
	*dlen_out = 0;

	const char *key = (argc >= 1) ? argv[0] : NULL;
	const char *val = (argc >= 2) ? argv[1] : NULL;

	// 基本参数校验（按你原有命令语义）
	switch (op) {
	case KVS_CMD_SET:
	case KVS_CMD_MOD:
	case KVS_CMD_RSET:
	case KVS_CMD_RMOD:
	case KVS_CMD_HSET:
	case KVS_CMD_HMOD:
		if (argc != 2 || !key || !val) { *status_out = KVS_STATUS_BADREQ; return; }
		break;
	case KVS_CMD_GET:
	case KVS_CMD_DEL:
	case KVS_CMD_EXIST:
	case KVS_CMD_RGET:
	case KVS_CMD_RDEL:
	case KVS_CMD_REXIST:
	case KVS_CMD_HGET:
	case KVS_CMD_HDEL:
	case KVS_CMD_HEXIST:
		if (argc != 1 || !key) { *status_out = KVS_STATUS_BADREQ; return; }
		break;
	default:
		*status_out = KVS_STATUS_BADREQ;
		return;
	}

	int ret = 0;
	const char *result = NULL;

	switch (op) {
#if ENABLE_ARRAY
	case KVS_CMD_SET:
		ret = kvs_array_set(&global_array, (char*)key, (char*)val);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_EXIST;
		return;

	case KVS_CMD_GET:
		result = kvs_array_get(&global_array, (char*)key);
		if (!result) { *status_out = KVS_STATUS_NO_EXIST; return; }
		*status_out = KVS_STATUS_OK;
		*data_out = result;
		*dlen_out = (uint32_t)strlen(result);
		return;

	case KVS_CMD_DEL:
		ret = kvs_array_del(&global_array, (char*)key);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_NO_EXIST;
		return;

	case KVS_CMD_MOD:
		ret = kvs_array_mod(&global_array, (char*)key, (char*)val);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_NO_EXIST;
		return;

	case KVS_CMD_EXIST:
		ret = kvs_array_exist(&global_array, (char*)key);
		*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
		return;
#endif

#if ENABLE_RBTREE
	case KVS_CMD_RSET:
		ret = kvs_rbtree_set(&global_rbtree, (char*)key, (char*)val);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_EXIST;
		return;

	case KVS_CMD_RGET:
		result = kvs_rbtree_get(&global_rbtree, (char*)key);
		if (!result) { *status_out = KVS_STATUS_NO_EXIST; return; }
		*status_out = KVS_STATUS_OK;
		*data_out = result;
		*dlen_out = (uint32_t)strlen(result);
		return;

	case KVS_CMD_RDEL:
		ret = kvs_rbtree_del(&global_rbtree, (char*)key);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_NO_EXIST;
		return;

	case KVS_CMD_RMOD:
		ret = kvs_rbtree_mod(&global_rbtree, (char*)key, (char*)val);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_NO_EXIST;
		return;

	case KVS_CMD_REXIST:
		ret = kvs_rbtree_exist(&global_rbtree, (char*)key);
		*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
		return;
#endif

#if ENABLE_HASH
	case KVS_CMD_HSET:
		ret = kvs_hash_set(&global_hash, (char*)key, (char*)val);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_EXIST;
		return;

	case KVS_CMD_HGET:
		result = kvs_hash_get(&global_hash, (char*)key);
		if (!result) { *status_out = KVS_STATUS_NO_EXIST; return; }
		*status_out = KVS_STATUS_OK;
		*data_out = result;
		*dlen_out = (uint32_t)strlen(result);
		return;

	case KVS_CMD_HDEL:
		ret = kvs_hash_del(&global_hash, (char*)key);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_NO_EXIST;
		return;

	case KVS_CMD_HMOD:
		ret = kvs_hash_mod(&global_hash, (char*)key, (char*)val);
		if (ret < 0) *status_out = KVS_STATUS_ERROR;
		else if (ret == 0) *status_out = KVS_STATUS_OK;
		else *status_out = KVS_STATUS_NO_EXIST;
		return;

	case KVS_CMD_HEXIST:
		ret = kvs_hash_exist(&global_hash, (char*)key);
		*status_out = (ret == 0) ? KVS_STATUS_EXIST : KVS_STATUS_NO_EXIST;
		return;
#endif
	default:
		*status_out = KVS_STATUS_BADREQ;
		return;
	}
}

#if NEW_KVSTORE
// int kvs_protocol(char *msg, int length, char *response, int *response_len){
int kvs_protocol(char *msg, int length, char *response){
	if (!msg || length <= 0 || !response) return 0;
	int response_len = 0;

	kvs_request_t req;
	int consumed = kvs_parse_request((const uint8_t *)msg, length, &req);
	
	if (consumed < 0) return 0;			// 解析失败
	else if(consumed == 0) return 0;	// 半包 


	kvs_response_t *results = (kvs_response_t *)kvs_malloc(sizeof(kvs_response_t) * req.opcount);
	if (!results) { kvs_free_request(&req); return -1; }
	memset(results, 0, sizeof(kvs_response_t) * req.opcount);

	if (kvs_execute_request(&req, results) < 0) {
		kvs_free(results);
		kvs_free_request(&req);
		return -1;
	}

	int resp_len = kvs_build_response(&req, results, (uint8_t *)response, KVS_MAX_RESPONSE);
	kvs_free(results);
	kvs_free_request(&req);

	if (resp_len < 0) return 0;	// error

	response_len = resp_len;
	return response_len;
}
#else
/*
 * msg: request message
 * length: length of request message
 * response: need to send
 * @return : length of response
 */

int kvs_protocol(char *msg, int length, char *response) {  //
	
// SET Key Value
// GET Key
// DEL Key
	if (msg == NULL || length <= 0 || response == NULL) return -1;

	//printf("recv %d : %s\n", length, msg);

	char *tokens[KVS_MAX_TOKENS] = {0};

	int count = kvs_split_token(msg, tokens);
	if (count == -1) return -1;

	//memcpy(response, msg, length);

	return kvs_filter_protocol(tokens, count, response);
}
#endif

int init_kvengine(void) {

#if ENABLE_ARRAY
	memset(&global_array, 0, sizeof(kvs_array_t));
	kvs_array_create(&global_array);
#endif

#if ENABLE_RBTREE
	memset(&global_rbtree, 0, sizeof(kvs_rbtree_t));
	kvs_rbtree_create(&global_rbtree);
#endif

#if ENABLE_HASH
	memset(&global_hash, 0, sizeof(kvs_hash_t));
	kvs_hash_create(&global_hash);
#endif

	return 0;
}

void dest_kvengine(void) {
#if ENABLE_ARRAY
	kvs_array_destory(&global_array);
#endif
#if ENABLE_RBTREE
	kvs_rbtree_destory(&global_rbtree);
#endif
#if ENABLE_HASH
	kvs_hash_destory(&global_hash);
#endif

}



int main(int argc, char *argv[]) {

	if (argc != 2) return -1;

	int port = atoi(argv[1]);

	init_kvengine();
	
	
#if (NETWORK_SELECT == NETWORK_REACTOR)
	reactor_start(port, kvs_protocol);  //
#elif (NETWORK_SELECT == NETWORK_PROACTOR)
	proactor_start(port, kvs_protocol);
#elif (NETWORK_SELECT == NETWORK_NTYCO)
	ntyco_start(port, kvs_protocol);
#endif

	dest_kvengine();

}


