

#include "kvstore.h"
#include "kvs_rw_tools.h"
#include "mem_pool/mem_pool.h"
#include <arpa/inet.h>


// singleton

kvs_array_t global_array = {0};

int kvs_array_create(kvs_array_t *inst) {

	if (!inst) return -1;
	if (inst->table) {
		printf("table has alloc\n");
		return -1;
	}	
	inst->table = kvs_malloc(KVS_ARRAY_SIZE * sizeof(kvs_array_item_t));
	if (!inst->table) {
		return -1;
	}

	memset(inst->table, 0, (size_t)KVS_ARRAY_SIZE * sizeof(kvs_array_item_t));
	inst->total = 0;

	return 0;
}

void kvs_array_destroy(kvs_array_t *inst) {

	if (!inst) return ;

	if (inst->table) {
		kvs_free(inst->table);
	}

}

/**
 * return: ==-2 not exist, == -1 error, >= 0 exist idx
 */
int kvs_array_find_index(kvs_array_t *inst, const void *key, uint32_t key_len) {
    if (!inst || !inst->table || !key) return -1;
    for (int i = 0; i < inst->total; i++) {
        kvs_array_item_t *it = &inst->table[i];
        if (!it->key) continue;
        if (it->key_len == key_len && memcmp(it->key, key, key_len) == 0) {
            return i;
        }
    }
    return -2; // not found
}

/*
 * return: <0 error; 0 success; 1 exist
 */
int kvs_array_set_bin(kvs_array_t *inst,
                      const void *key, uint32_t key_len,
                      const void *value, uint32_t value_len) {
    if (!inst || !inst->table || !key || key_len == 0 || !value) return -1;
    if (inst->total >= KVS_ARRAY_SIZE) return -1;

    int idx = kvs_array_find_index(inst, key, key_len);
	// -2 not exist
    if (idx >= 0) return 1;     // exist
    if (idx == -1) return -1;   // error

    uint8_t *kcopy = (uint8_t *)kvs_malloc(key_len);
    if (!kcopy) return -2;
    memcpy(kcopy, key, key_len);

    uint8_t *vcopy = NULL;
    if (value_len > 0) {
        vcopy = (uint8_t *)kvs_malloc(value_len);
        if (!vcopy) {
            kvs_free(kcopy);
            return -2;
        }
        memcpy(vcopy, value, value_len);
    } else {
        // 允许空 value（长度0），value 指针置 NULL
        vcopy = NULL;
    }

	int i = 0;
	for (i = 0;i < inst->total;i ++) {
		if (inst->table[i].key == NULL) {
			
			inst->table[i].key = kcopy;
    		inst->table[i].key_len = key_len;
			inst->table[i].value = vcopy;
			inst->table[i].value_len = value_len;
			inst->total ++;
			
			return 0;
		}
	}

	if (i == inst->total && i < KVS_ARRAY_SIZE) {

		inst->table[i].key = kcopy;
		inst->table[i].key_len = key_len;
		inst->table[i].value = vcopy;
		inst->table[i].value_len = value_len;
		inst->total ++;
	}

    return 0;
}

/*
 * @return: NULL notexist, NOTNULL exist
 */
void *kvs_array_get_bin(kvs_array_t *inst, const void *key, uint32_t key_len, uint32_t *out_value_len) {
    if (out_value_len) *out_value_len = 0;
    if (!inst || !inst->table || !key || key_len == 0) return NULL;

    int idx = kvs_array_find_index(inst, key, key_len);
    if (idx < 0) return NULL;

    kvs_array_item_t *it = &inst->table[idx];
    if (out_value_len) *out_value_len = it->value_len;
    return it->value; // 注意：由 store 持有
}

/*
 * @return < 0, error;  =0,  success; >0, no exist
 */
int kvs_array_del_bin(kvs_array_t *inst, const void *key, uint32_t key_len) {
    if (!inst || !inst->table || !key || key_len == 0) return -1;

    int idx = kvs_array_find_index(inst, key, key_len);
    if (idx == -2) return 1;  // not exist
    if (idx < 0) return -1;

    kvs_array_item_t *it = &inst->table[idx];
    if (it->key) kvs_free(it->key);
    if (it->value) kvs_free(it->value);

    // 用末尾元素填洞，保证 total 连续，避免 “total 只增不减” 问题
    int last = inst->total - 1;
    if (idx != last) {
        inst->table[idx] = inst->table[last];
    }

    // 清理末尾（已被移动或删除）
    memset(&inst->table[last], 0, sizeof(kvs_array_item_t));
    inst->total--;

    return 0;
}

/*
 * @return : < 0, error; =0, success; >0, no exist 
 */

int kvs_array_mod_bin(kvs_array_t *inst,
                      const void *key, uint32_t key_len,
                      const void *value, uint32_t value_len) {
    if (!inst || !inst->table || !key || key_len == 0 || !value) return -1;

    int idx = kvs_array_find_index(inst, key, key_len);
    if (idx == -2) return 1; // not exist
    if (idx < 0) return -1;

    kvs_array_item_t *it = &inst->table[idx];

    uint8_t *vcopy = NULL;
    if (value_len > 0) {
        vcopy = (uint8_t *)kvs_malloc(value_len);
        if (!vcopy) return -2;
        memcpy(vcopy, value, value_len);
    } else {
        vcopy = NULL;
    }

    if (it->value) kvs_free(it->value);
    it->value = vcopy;
    it->value_len = value_len;

    return 0;
}

/*
 * @return 0: exist, 1: no exist
 */
int kvs_array_exist_bin(kvs_array_t *inst, const void *key, uint32_t key_len) {
    if (!inst || !inst->table || !key || key_len == 0) return -1;
    int idx = kvs_array_find_index(inst, key, key_len);
    return (idx >= 0) ? 0 : 1;
}

// return: 0 success, <0 error
int kvs_array_save(kvs_array_t *inst, const char* filename){
	if(!inst || !filename) return -1;
	FILE *fp = fopen(filename, "wb");
	if(!fp) return -2;


	for(int i = 0;i < inst->total; ++ i){
		kvs_array_item_t *it = &inst->table[i];
		if(!it->key || it->key_len == 0) continue;	// 跳过空槽
		if(it->value_len > 0 && !it->value) { fclose(fp); return -3; }

		uint32_t klen = htonl(it->key_len);
		uint32_t vlen = htonl(it->value_len);

		if (kvs_write_file(fp, &klen, 4) < 0) { fclose(fp); return -4; }
        if (kvs_write_file(fp, &vlen, 4) < 0) { fclose(fp); return -4; }

		if (kvs_write_file(fp, it->key, it->key_len) < 0) { fclose(fp); return -4; }
        if (it->value_len > 0) {
            if (kvs_write_file(fp, it->value, it->value_len) < 0) { fclose(fp); return -4; }
        }
	}

	fclose(fp);
	return 0;
}

int kvs_array_load(kvs_array_t *inst, const char* filename) {
	if (!inst || !filename) return -1;
    if (!inst->table) return -1;

	FILE *fp = fopen(filename, "rb");
    if (!fp) return -2;

	int idx = 0;
	while(1){
		uint32_t klen_n = 0, vlen_n = 0;

		if (kvs_read_file(fp, &klen_n, 4) < 0) { fclose(fp); return -3; }
		if (kvs_read_file(fp, &vlen_n, 4) < 0) { fclose(fp); return -3; }
		
        uint32_t klen = ntohl(klen_n);
        uint32_t vlen = ntohl(vlen_n);

		if (klen == 0) { fclose(fp); return -3; }

		kvs_array_item_t *it = &inst->table[idx];
        memset(it, 0, sizeof(*it));

		it->key = (uint8_t *)kvs_malloc(klen);
        if (!it->key) { fclose(fp); return -3; }
        it->key_len = klen;
		if (kvs_read_file(fp, it->key, klen) < 0) { fclose(fp); return -3; }

		if (vlen > 0) {
            it->value = (uint8_t *)kvs_malloc(vlen);
            if (!it->value) { fclose(fp); return -4; }
            it->value_len = vlen;

            if (kvs_read_file(fp, it->value, vlen) < 0) { fclose(fp); return -3; }
        } else {
            it->value = NULL;
            it->value_len = 0;
        }
		
		inst->total ++;
		idx++;
		if(idx >= KVS_ARRAY_SIZE){ break; }
	}

	fclose(fp);
    return 0;
}
