#include "hal_minifds.h"
#include "cli.h"

#define MINIFDS_PRINTF 0
#if MINIFDS_PRINTF
#include "SEGGER_RTT.h"
#include "cli.h"
#define DEBUG_LOG_MINIFDS DEBUG_LOG
#else
#define DEBUG_LOG_MINIFDS(...) ;
#endif

#define ALIGN_WORD(x) ((x) % 4 == 0 ? (x) : (((x) / 4 + 1) * 4)) //例如 33->36
#define PARAMETER_CHECK(x) 

static char checkcec(uint32_t addr)
{
	uint8_t crc = 0;
	minfds_record_t* recordhend = (minfds_record_t*)addr;
	for (int i = 0; i < recordhend->length; i++)
	{
		crc += ((uint8_t*)(addr + sizeof(minfds_record_t)))[i];
	}
	if (crc == recordhend->crc8)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

static uint32_t jump(uint32_t addr)
{
	minfds_record_t* recordhend = (minfds_record_t*)addr;
	return addr + ALIGN_WORD(recordhend->length + sizeof(minfds_record_t));
}

void printctb(minfds_t* p_minifds)
{
	DEBUG_LOG_MINIFDS("   free_capacity  %6d bytes\r\n", p_minifds->free_capacity);
	DEBUG_LOG_MINIFDS("   duty_capacity  %6d bytes\r\n", p_minifds->duty_capacity);
	DEBUG_LOG_MINIFDS("   FFFFFFFF                                   %6d bytes\r\n", p_minifds->free_capacity - p_minifds->duty_capacity);
	DEBUG_LOG_MINIFDS("   record_count   %3d\r\n", p_minifds->record_count);
}

void print_record(uint8_t* data, length_t length)
{
	for (int i = 0; i < length; i++)
	{
		if (i % 16 == 0)
		{
			DEBUG_LOG_MINIFDS("\r\n %4d ", i);
#if MINIFDS_PRINTF
			for (int k = 0; k < 0xffff; k++)
				;
#endif
		}
		DEBUG_LOG_MINIFDS("%2x ", data[i]);
	}
	DEBUG_LOG_MINIFDS("\r\n");
}

char minfds_Scan(minfds_t* p_minifds)
{
	uint32_t hendaddress = p_minifds->start_addr;
	minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
	p_minifds->duty_capacity = 0;
	p_minifds->free_capacity = p_minifds->end_addr - p_minifds->start_addr;
	p_minifds->record_count = 0;
	DEBUG_LOG_MINIFDS("   minfds_Scan  start !!!!!\r\n");
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (uint32_t)hendaddress == p_minifds->end_addr)
		{
			for (uint32_t addr = hendaddress; addr < p_minifds->end_addr; addr++)
			{
				if (*(uint8_t*)addr != 0xff)
				{
					DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE 0XFFFF   0x%x !!!!!\r\n", addr);
					return MINIFDS_ERR_HARDWARE;
				}
			}
			DEBUG_LOG_MINIFDS("   minfds_Scan  end !!!!!\r\n");
			return MINIFDS_SUCCESS;
		}
		else
		{
			recordhend = (minfds_record_t*)hendaddress;
			if (checkcec(hendaddress))
			{
				DEBUG_LOG_MINIFDS("Record addr %x  Key %3d  length %d  %d CRC OK\r\n", (uint32_t)recordhend, recordhend->record_key, recordhend->length, ALIGN_WORD(recordhend->length + sizeof(minfds_record_t)));
				if (recordhend->record_key == 0)
				{
					p_minifds->duty_capacity += ALIGN_WORD(recordhend->length + sizeof(minfds_record_t));
				}
				else
				{
					p_minifds->record_count++;
					p_minifds->free_capacity -= ALIGN_WORD(recordhend->length + sizeof(minfds_record_t));
				}
			}
			else
			{
				DEBUG_LOG_MINIFDS("Record Key %3d : CRCERROR !!!!!\r\n", recordhend->record_key);
			}
			//                      print_record((uint8_t*)(hendaddress+sizeof(minfds_record_t)),recordhend->length);
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE    : 0x%x\r\n", hendaddress);
				return MINIFDS_ERR_HARDWARE;
			}
		}
	}
}

unsigned short minfds_record_count_get(minfds_t* p_minifds)
{
	return p_minifds->record_count;
}

char minfds_gc(minfds_t* p_minifds)
{
#define WRITE_TINES 8
	uint8_t gcbuffer[4096];
	uint32_t duty_recodecount = 0;
	uint32_t recodecount = 0;
	uint32_t gcbuffer_index = 0;
	uint32_t erase_page_addr = p_minifds->start_addr; //接下来要擦除的扇区地址
	uint32_t write_page_addr = p_minifds->start_addr; //接下来要的写地址
	flash_OPER_Result rev = FLASH_OP_SUCCESS;
	unsigned short length;
	minfds_record_t* next_recordhend;
	minfds_record_t* recordhend = (minfds_record_t*)p_minifds->start_addr;
	DEBUG_LOG_MINIFDS("----------------------------gc s-------------------------- \r\n");
	printctb(p_minifds);
	p_minifds->free_capacity = p_minifds->end_addr - p_minifds->start_addr;
	while (1)
	{
		if ((*(uint32_t*)recordhend == 0xffffffff) || (uint32_t)recordhend == p_minifds->end_addr)
		{
			if (duty_recodecount == 0)
			{
				break;
			}
			p_minifds->api.flash_page_erase(erase_page_addr);
			DEBUG_LOG_MINIFDS("flash_page_erase(1) %x  %x\r\n", erase_page_addr, write_page_addr);
			//---------write---------
			DEBUG_LOG_MINIFDS("write2 >= %x len =%d\r\n", write_page_addr, gcbuffer_index);
			for (int i = 0; i < gcbuffer_index / (4096 / WRITE_TINES); i++)
			{
				rev = p_minifds->api.flash_write(
					(uint32_t*)(write_page_addr + i * (4096 / WRITE_TINES)),
					(uint32_t*)(gcbuffer + i * (4096 / WRITE_TINES)),
					4096 / 4 / WRITE_TINES);
			}
			if (gcbuffer_index % (4096 / WRITE_TINES) != 0)
			{
				rev = p_minifds->api.flash_write(
					(uint32_t*)(write_page_addr + (gcbuffer_index / (4096 / WRITE_TINES)) * (4096 / WRITE_TINES)),
					(uint32_t*)(gcbuffer + (gcbuffer_index / (4096 / WRITE_TINES)) * (4096 / WRITE_TINES)),
					(gcbuffer_index % (4096 / WRITE_TINES)) % 4 == 0 ? (gcbuffer_index % (4096 / WRITE_TINES)) / 4 : (gcbuffer_index % (4096 / WRITE_TINES)) / 4 + 1);
			}
			break;
		}
		else if (recordhend->record_key == 0)
		{
			duty_recodecount++;
			DEBUG_LOG_MINIFDS(" %3d page %2d :key duty, length %5d addr: %x\r\n", duty_recodecount, (erase_page_addr - p_minifds->start_addr) / 4096, recordhend->length, (uint32_t)recordhend);
			p_minifds->duty_capacity -= ALIGN_WORD(recordhend->length + sizeof(minfds_record_t));
			next_recordhend = (minfds_record_t*)jump((uint32_t)recordhend);
			recordhend = next_recordhend;
			if ((uint32_t)recordhend > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("    MINIFDS_ERR_HARDWARE   0x%x\r\n", (uint32_t)recordhend);
				return MINIFDS_ERR_HARDWARE;
			}
			while ((uint32_t)recordhend >= erase_page_addr + 4096)
			{
				p_minifds->api.flash_page_erase(erase_page_addr);
				erase_page_addr += 4096;
				DEBUG_LOG_MINIFDS("flash_page_erase(2) %x  %x\r\n", erase_page_addr - 4096, write_page_addr);
			}
		}
		else
		{
			recodecount++;
			p_minifds->free_capacity -= ALIGN_WORD(recordhend->length + sizeof(minfds_record_t));
			DEBUG_LOG_MINIFDS(" %3d page %2d :key %3d , length %5d addr: %x\r\n", recodecount, (erase_page_addr - p_minifds->start_addr) / 4096, recordhend->record_key, recordhend->length, (uint32_t)recordhend);
			next_recordhend = (minfds_record_t*)jump((uint32_t)recordhend);
			if ((uint32_t)next_recordhend > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("    MINIFDS_ERR_HARDWARE 118   0x%x\r\n", (uint32_t)next_recordhend);
				return MINIFDS_ERR_HARDWARE;
			}
			length = (uint32_t)next_recordhend - (uint32_t)recordhend;
			for (uint32_t i = 0; i < length; i++)
			{
				gcbuffer[gcbuffer_index] = ((uint8_t*)recordhend)[i];
				gcbuffer_index++;
				if (gcbuffer_index >= 4096)
				{
					gcbuffer_index = 0;
					DEBUG_LOG_MINIFDS("gcbuffer_index >= 4096\r\n");
					while (erase_page_addr <= write_page_addr)
					{
						p_minifds->api.flash_page_erase(erase_page_addr);
						erase_page_addr += 4096;
						DEBUG_LOG_MINIFDS("flash_page_erase(3) %x  %x\r\n", erase_page_addr - 4096, write_page_addr);
					}
					//---------write---------
					DEBUG_LOG_MINIFDS("write >= %x len =%d\r\n", write_page_addr, 4096);
					for (int j = 0; j < WRITE_TINES; j++)
					{
						rev = p_minifds->api.flash_write(
							(uint32_t*)(write_page_addr + j * (4096 / WRITE_TINES)),
							(uint32_t*)(gcbuffer + j * (4096 / WRITE_TINES)),
							4096 / 4 / WRITE_TINES);
					}
					write_page_addr += 4096;
				}
			}
			while ((uint32_t)next_recordhend >= erase_page_addr + 4096)
			{
				p_minifds->api.flash_page_erase(erase_page_addr);
				erase_page_addr += 4096;
				DEBUG_LOG_MINIFDS("flash_page_erase(4) %x  %x\r\n", erase_page_addr - 4096, write_page_addr);
			}
			recordhend = next_recordhend;
		}
#if MINIFDS_PRINTF
		for (int k = 0; k < 0xffff; k++);
#endif
	}
	if (rev != FLASH_OP_SUCCESS)
	{
		DEBUG_LOG_MINIFDS("    MINIFDS_ERR_API_FAIL    0x%x\r\n", (uint32_t)p_minifds->duty_capacity);
		return MINIFDS_ERR_API_FAIL;
	}
	printctb(p_minifds);
	DEBUG_LOG_MINIFDS("----------------------------gc e-------------------------- \r\n");
	return 0;
}

char minfds_record_add(minfds_t* p_minifds, key_t key, uint8_t* data, length_t length)
{
	uint32_t sizewords;
	uint32_t rev;
	uint32_t hendaddress = p_minifds->start_addr;
	DEBUG_LOG_MINIFDS("minfds_record_add  : \r\n");
	printctb(p_minifds);
	DEBUG_LOG_MINIFDS(" Key =  %d  length = %d ,  4klen:%d\r\n", key, length, ALIGN_WORD(length + sizeof(minfds_record_t)));
	if (length > MAX_RECORD_LENGTH)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_LENGTH length=%d\r\n", length);
		return MINIFDS_ERR_REPEAT_LENGTH;
	}
	if (key == 0)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY key=0\r\n");
		return MINIFDS_ERR_REPEAT_KEY;
	}
	if (p_minifds->free_capacity < ALIGN_WORD(length + sizeof(minfds_record_t)))
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_NOT_FREE_CAPACITY\r\n");
		return MINIFDS_ERR_NOT_FREE_CAPACITY;
	}
	if (p_minifds->free_capacity - p_minifds->duty_capacity < ALIGN_WORD(length + sizeof(minfds_record_t)))
	{
		DEBUG_LOG_MINIFDS(" minfds_record_add   minfds_gc(p_minifds);  %d,%d \r\n", p_minifds->duty_capacity, p_minifds->free_capacity);
		rev = minfds_gc(p_minifds);
		if (rev != 0)
		{
			DEBUG_LOG_MINIFDS(" minfds_record_add   minfds_gc ERROR ;  %d,%d \r\n", rev, p_minifds->free_capacity);
			return rev;
		}
	}
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (uint32_t)hendaddress == p_minifds->end_addr)
		{
			minfds_record_t hend;
			hend.record_key = key;
			hend.length = length;
			hend.crc8 = 0;
			for (int i = 0; i < length; i++)
			{
				hend.crc8 += data[i];
			}
			sizewords = length;
			if (sizewords % 4 != 0)
			{
				sizewords = sizewords / 4 + 1;
			}
			else
			{
				sizewords = sizewords / 4;
			}
			DEBUG_LOG_MINIFDS(" writaddr 0x%x ,nextaddr 0x%x             %d\r\n", hendaddress, hendaddress + ALIGN_WORD(hend.length + sizeof(minfds_record_t)), p_minifds->end_addr - hendaddress);
			p_minifds->free_capacity -= ALIGN_WORD(length + sizeof(minfds_record_t));

			for (int a = 0; a < ALIGN_WORD(hend.length + sizeof(minfds_record_t)); a++)
			{
				if (*(uint8_t*)(hendaddress + a) != 0xff)
				{
					DEBUG_LOG_MINIFDS("flash data  :\r\n");
					print_record((uint8_t*)(hendaddress + sizeof(minfds_record_t)), sizewords * 4);
					DEBUG_LOG_MINIFDS("Ram data  :\r\n");
					print_record(data, sizewords * 4);
					DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE NOT 0xFF\r\n");
					return MINIFDS_ERR_HARDWARE;
				}
			}

			rev = p_minifds->api.flash_write((uint32_t*)hendaddress, (uint32_t*)&hend, sizeof(minfds_record_t) / 4);
			if (rev != FLASH_OP_SUCCESS)
			{
				printctb(p_minifds);
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_API_FAIL flash_write 1 %d   0x%x  0x%x  0x%x\r\n", rev, (uint32_t*)hendaddress, (uint32_t*)&hend, sizeof(minfds_record_t) / 4);
				return MINIFDS_ERR_API_FAIL;
			}
			if (sizewords != 0)
			{
				rev = p_minifds->api.flash_write((uint32_t*)(hendaddress + sizeof(minfds_record_t)), (uint32_t*)data, sizewords);
			}
			if (rev == FLASH_OP_SUCCESS)
			{
				p_minifds->record_count++;
				if (checkcec(hendaddress) != 1)
				{
					DEBUG_LOG_MINIFDS("flash data  :\r\n");
					print_record((uint8_t*)(hendaddress + sizeof(minfds_record_t)), sizewords * 4);
					DEBUG_LOG_MINIFDS("Ram data  :\r\n");
					print_record(data, sizewords * 4);
					DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE CRC\r\n");
					return MINIFDS_ERR_HARDWARE;
				}
				DEBUG_LOG_MINIFDS("MINIFDS_SUCCESS\r\n");
				return MINIFDS_SUCCESS;
			}
			else
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_API_FAIL flash_write 2 %d   0x%x  0x%x  0x%x\r\n", rev, (uint32_t*)(hendaddress + sizeof(minfds_record_t)), (uint32_t*)data, sizewords);
				return MINIFDS_ERR_API_FAIL;
			}
		}
		else
		{
			minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
			if (recordhend->record_key == key)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY\r\n");
				return MINIFDS_ERR_REPEAT_KEY;
			}
			if (!checkcec(hendaddress))
			{
				DEBUG_LOG_MINIFDS("    MINIFDS_ERR_HARDWARE CRC add   0x%x\r\n", hendaddress);
				return MINIFDS_ERR_HARDWARE;
			}
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("    MINIFDS_ERR_HARDWARE 426   0x%x\r\n", hendaddress);
				return MINIFDS_ERR_HARDWARE;
			}
		}
	}
}

char minfds_record_find(minfds_t* p_minifds, key_t key, uint8_t* data, length_t* length)
{
	uint32_t hendaddress = p_minifds->start_addr;
	minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
	DEBUG_LOG_MINIFDS("minfds_record_find  : \r\n");
	DEBUG_LOG_MINIFDS(" Key =  %d \r\n", key);
	if (key == 0)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY key=0\r\n");
		return MINIFDS_ERR_REPEAT_KEY;
	}
	if (*length == 0)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_LENGTH *length=0\r\n");
		return MINIFDS_ERR_REPEAT_LENGTH;
	}
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (hendaddress == p_minifds->end_addr))
		{
			DEBUG_LOG_MINIFDS("MINIFDS_ERR_NOT_FIND_RECORD \r\n");
			return MINIFDS_ERR_NOT_FIND_RECORD;
		}
		else if (recordhend->record_key == key)
		{
			if (*length < recordhend->length)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_LENGTH *length=%d\r\n", *length);
				return MINIFDS_ERR_REPEAT_LENGTH;
			}
			memcpy(data, (uint8_t*)(hendaddress + sizeof(minfds_record_t)), recordhend->length);
			*length = recordhend->length;
			DEBUG_LOG_MINIFDS(" length =  %d \r\n", recordhend->length);
			return MINIFDS_SUCCESS;
		}
		else
		{
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE \r\n");
				return MINIFDS_ERR_HARDWARE;
			}
			recordhend = (minfds_record_t*)hendaddress;
		}
	}
}

char get_record_hendaddr(minfds_t* p_minifds, key_t key, uint32_t* addr)
{
	uint32_t hendaddress = p_minifds->start_addr;
	minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
	DEBUG_LOG_MINIFDS("minfds_record_get_length  : \r\n");
	DEBUG_LOG_MINIFDS(" Key =  %d \r\n", key);
	if (key == 0)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY key=0\r\n");
		return MINIFDS_ERR_REPEAT_KEY;
	}
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (hendaddress == p_minifds->end_addr))
		{
			DEBUG_LOG_MINIFDS("MINIFDS_ERR_NOT_FIND_RECORD \r\n");
			return MINIFDS_ERR_NOT_FIND_RECORD;
		}
		else if (recordhend->record_key == key)
		{
			*addr = (uint32_t)recordhend;
			DEBUG_LOG_MINIFDS(" addr =  %x \r\n", *addr);
			return MINIFDS_SUCCESS;
		}
		else
		{
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE \r\n");
				return MINIFDS_ERR_HARDWARE;
			}
			recordhend = (minfds_record_t*)hendaddress;
		}
	}
}

char minfds_record_get_length(minfds_t* p_minifds, key_t key, length_t* length)
{
	char rev = 0;
	uint32_t addr_hend = 0;
	minfds_record_t* recordhend = NULL;
	rev = get_record_hendaddr(p_minifds, key, &addr_hend);
	if (rev != MINIFDS_SUCCESS)return rev;
	recordhend = (minfds_record_t*)addr_hend;
	*length = recordhend->length;
	return MINIFDS_SUCCESS;
}

char minfds_record_find_mem(minfds_t* p_minifds, uint8_t* mem, int mem_len, key_t* key)
{
	uint32_t hendaddress = p_minifds->start_addr;
	minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
	DEBUG_LOG_MINIFDS("minfds_record_find_mem  : \r\n");
	DEBUG_LOG_MINIFDS(" mem_len =  %d \r\n", mem_len);
	DEBUG_LOG_MINIFDS(" mem_len254 =  %d \r\n", 100);
	DEBUG_LOG_MINIFDS("  [%s] \r\n", mem);
	if ((mem_len == 0) || (mem == NULL))
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY key=0\r\n");
		return MINIFDS_ERR_REPEAT_KEY;
	}
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (hendaddress == p_minifds->end_addr))
		{
			DEBUG_LOG_MINIFDS("MINIFDS_ERR_NOT_FIND_RECORD \r\n");
			return MINIFDS_ERR_NOT_FIND_RECORD;
		}
		else if (recordhend->record_key != 0)
		{
			if (recordhend->length >= mem_len)
			{
				for (int i = 0;i < recordhend->length - mem_len;i++)
				{
					if (memcmp(mem, (uint8_t*)(hendaddress + i + sizeof(minfds_record_t)), mem_len) == 0)
					{
						*key = recordhend->record_key;
						DEBUG_LOG_MINIFDS("MINIFDS_SUCCESS -----\r\n");
						return MINIFDS_SUCCESS;
					}
				}
			}
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE \r\n");
				return MINIFDS_ERR_HARDWARE;
			}
			recordhend = (minfds_record_t*)hendaddress;
		}
		else
		{
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE \r\n");
				return MINIFDS_ERR_HARDWARE;
			}
			recordhend = (minfds_record_t*)hendaddress;
		}
	}
}

char minfds_record_update(minfds_t* p_minifds, key_t key, uint8_t* data, length_t length)
{
	uint32_t hendaddr = 0;
	char rev = 0;
	if (key == 0)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY key=0\r\n");
		return MINIFDS_ERR_REPEAT_KEY;
	}
	DEBUG_LOG_MINIFDS("minfds_record_update key=%d\r\n", key);
	rev = get_record_hendaddr(p_minifds, key, &hendaddr);
	if (rev == MINIFDS_SUCCESS)
	{
		minfds_record_t* recordhend = (minfds_record_t*)hendaddr;
		if (recordhend->length == length)
		{
			if (memcmp((uint8_t*)(hendaddr + sizeof(minfds_record_t)), data, length) == 0)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_SUCCESS NOT NEED UPDATE\r\n");
				return MINIFDS_SUCCESS;
			}
		}
	}

	rev = minfds_record_delete(p_minifds, key);
	if (rev != 0)
	{
		return rev;
	}
	return minfds_record_add(p_minifds, key, data, length);
}

char minfds_record_delete(minfds_t* p_minifds, key_t key)
{
	uint32_t hendaddress = p_minifds->start_addr;
	flash_OPER_Result rev;
	minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
	DEBUG_LOG_MINIFDS("minfds_record_delete  :  key %d  ", key);
	if (key == 0)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY key=0\r\n");
		return MINIFDS_ERR_REPEAT_KEY;
	}
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (uint32_t)hendaddress == p_minifds->end_addr)
		{
			DEBUG_LOG_MINIFDS("MINIFDS_ERR_NOT_FIND_RECORD  record_count %d\r\n", p_minifds->record_count);
			return MINIFDS_ERR_NOT_FIND_RECORD;
		}
		if (recordhend->record_key == key)
		{
			minfds_record_t temp;
			memcpy(&temp, recordhend, sizeof(minfds_record_t));
			temp.record_key = 0x00;
			p_minifds->duty_capacity += ALIGN_WORD(temp.length + sizeof(minfds_record_t));
			p_minifds->free_capacity += ALIGN_WORD(temp.length + sizeof(minfds_record_t));
			rev = p_minifds->api.flash_write((uint32_t*)hendaddress, (uint32_t*)&temp, sizeof(minfds_record_t) / 4);
			if (rev == FLASH_OP_SUCCESS)
			{
				if (memcmp(&temp, (uint32_t*)hendaddress, sizeof(minfds_record_t)) != 0)
				{
					DEBUG_LOG_MINIFDS("MINIFDS_ERR_API_FAIL1\r\n");
					return MINIFDS_ERR_API_FAIL;
				}
				DEBUG_LOG_MINIFDS("MINIFDS_SUCCESS\r\n");
				p_minifds->record_count--;
				return MINIFDS_SUCCESS;
			}
			else
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_API_FAIL2\r\n");
				return MINIFDS_ERR_API_FAIL;
			}
		}
		else
		{
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("    MINIFDS_ERR_HARDWARE   0x%x\r\n", hendaddress);
				return MINIFDS_ERR_HARDWARE;
			}
			recordhend = (minfds_record_t*)hendaddress;
		}
	}
}

char minfds_record_delete_all(minfds_t* p_minifds)
{
	uint32_t hendaddress = p_minifds->start_addr;
	uint32_t rev;
	minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
	DEBUG_LOG_MINIFDS("minfds_record_delete_all  : ");
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (uint32_t)hendaddress == p_minifds->end_addr)
		{
			return MINIFDS_SUCCESS;
		}
		if (recordhend->record_key != 0)
		{
			minfds_record_t temp;
			memcpy(&temp, recordhend, sizeof(minfds_record_t));
			temp.record_key = 0x00;
			p_minifds->duty_capacity += ALIGN_WORD(temp.length + sizeof(minfds_record_t));
			p_minifds->free_capacity += ALIGN_WORD(temp.length + sizeof(minfds_record_t));
			DEBUG_LOG_MINIFDS(" delete record_key : %d\r\n", recordhend->record_key);
			rev = p_minifds->api.flash_write((uint32_t*)hendaddress, (uint32_t*)&temp, sizeof(minfds_record_t) / 4);
			if (rev == FLASH_OP_SUCCESS)
			{
				p_minifds->record_count--;
			}
			else
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_API_FAIL\r\n");
				return MINIFDS_ERR_API_FAIL;
			}
		}
		else
		{
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("    MINIFDS_ERR_HARDWARE   0x%x\r\n", hendaddress);
				return MINIFDS_ERR_HARDWARE;
			}
			recordhend = (minfds_record_t*)hendaddress;
		}
	}
}

char minfds_format(minfds_t* p_minifds)
{
	for (int i = 0; i < (p_minifds->end_addr - p_minifds->start_addr) / 4096; i++)
	{
		p_minifds->api.flash_page_erase(p_minifds->start_addr + i * 4096);
	}
	p_minifds->duty_capacity = 0;
	p_minifds->record_count = 0;
	p_minifds->free_capacity = p_minifds->end_addr - p_minifds->start_addr;
	return MINIFDS_SUCCESS;
}

char minfds_init(minfds_t* p_minifds)
{
	DEBUG_LOG_MINIFDS("----------------------------------\r\n");
	DEBUG_LOG_MINIFDS("   Minfds Start_addr : 0x%x\r\n", p_minifds->start_addr);
	DEBUG_LOG_MINIFDS("   Minfds End_addr   : 0x%x \r\n", p_minifds->end_addr);
	minfds_Scan(p_minifds);
	printctb(p_minifds);
	DEBUG_LOG_MINIFDS("----------------------------------\r\n");
	return 0;
}

char record_index(minfds_t* p_minifds, minfds_record_t* record, uint8_t* data, int index)
{
	uint32_t hendaddress = p_minifds->start_addr;
	int i = 0;
	minfds_record_t* recordhend = (minfds_record_t*)hendaddress;
	DEBUG_LOG_MINIFDS("record_index  : \r\n");
	DEBUG_LOG_MINIFDS(" index =  %d \r\n", index);
	if ((index >= p_minifds->record_count) || (record == NULL) || (data == NULL))
	{
		//        DEBUG_LOG_MINIFDS("MINIFDS_ERR_PARAMETER \r\n");
		return MINIFDS_ERR_PARAMETER;
	}
	while (1)
	{
		if ((*(uint32_t*)hendaddress == 0xffffffff) || (hendaddress == p_minifds->end_addr))
		{
			DEBUG_LOG_MINIFDS("MINIFDS_ERR_NOT_FIND_RECORD \r\n");
			return MINIFDS_ERR_NOT_FIND_RECORD;
		}
		else if (recordhend->record_key != 0)
		{
			if (i == index)
			{
				data = (uint8_t*)(hendaddress + sizeof(minfds_record_t));
				record = recordhend;
				DEBUG_LOG_MINIFDS("MINIFDS_SUCCESS \r\n");
				return MINIFDS_SUCCESS;
			}
			i++;
		}
		else
		{
			hendaddress = jump(hendaddress);
			if (hendaddress > p_minifds->end_addr)
			{
				DEBUG_LOG_MINIFDS("MINIFDS_ERR_HARDWARE \r\n");
				return MINIFDS_ERR_HARDWARE;
			}
			recordhend = (minfds_record_t*)hendaddress;
		}
	}

}

char pm_add(minfds_t* p_minifds, const char* key, int key_len, unsigned char* data, length_t length)
{
	unsigned char buff[MAX_RECORD_LENGTH];
	key_t TEMP_KEY = 1;
	char rev = 0;
	if (key_len + length + 1 >= MAX_RECORD_LENGTH)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_LENGTH \r\n");
		return MINIFDS_ERR_REPEAT_LENGTH;
	}
	memcpy(buff, key, key_len);
	buff[key_len] = ':';
	rev = minfds_record_find_mem(p_minifds, buff, key_len + 1, &TEMP_KEY);
	if (rev == MINIFDS_SUCCESS)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_KEY \r\n");
		return MINIFDS_ERR_REPEAT_KEY;
	}
	memcpy(&buff[key_len + 1], data, length);
	while (1)
	{
		rev = minfds_record_add(p_minifds, TEMP_KEY, buff, key_len + length + 1);
		if (rev != MINIFDS_ERR_REPEAT_KEY)
		{
			return rev;
		}
		TEMP_KEY++;
		if (TEMP_KEY == 0)
		{
			return MINIFDS_ERR_REPEAT_KEY;
		}
	}
}

char pm_find(minfds_t* p_minifds, const char* key, int key_len, uint8_t* data, length_t* length)
{
	key_t TEMP_KEY = 1;
	char rev = 0;
	length_t temp_len = MAX_RECORD_LENGTH;
	uint8_t buff[MAX_RECORD_LENGTH];
	memcpy(buff, key, key_len);
	buff[key_len] = ':';
	rev = minfds_record_find_mem(p_minifds, buff, key_len + 1, &TEMP_KEY);
	if (rev != MINIFDS_SUCCESS)return rev;
	rev = minfds_record_find(p_minifds, TEMP_KEY, buff, &temp_len);
	if (rev != MINIFDS_SUCCESS)return rev;
	memcpy(data, &buff[key_len + 1], temp_len - key_len - 1);
	*length = temp_len - key_len - 1;
	return MINIFDS_SUCCESS;
}

char pm_get_length(minfds_t* p_minifds, const char* key, int key_len, length_t* length)
{
	key_t TEMP_KEY = 1;
	char rev = 0;
	length_t temp_len = 0;
	uint8_t buff[MAX_RECORD_LENGTH];
	memcpy(buff, key, key_len);
	buff[key_len] = ':';
	rev = minfds_record_find_mem(p_minifds, buff, key_len + 1, &TEMP_KEY);
	if (rev != MINIFDS_SUCCESS)return rev;
	rev = minfds_record_get_length(p_minifds, TEMP_KEY, &temp_len);
	*length = temp_len - key_len - 1;
	return rev;
}

char pm_delete(minfds_t* p_minifds, const char* key, int key_len)
{
	key_t TEMP_KEY = 1;
	char rev = 0;
	uint8_t buff[MAX_RECORD_LENGTH];
	memcpy(buff, key, key_len);
	buff[key_len] = ':';
	rev = minfds_record_find_mem(p_minifds, buff, key_len + 1, &TEMP_KEY);
	if (rev != MINIFDS_SUCCESS)return rev;
	rev = minfds_record_delete(p_minifds, TEMP_KEY);
	if (rev != MINIFDS_SUCCESS)return rev;
	return MINIFDS_SUCCESS;
}

char pm_update(minfds_t* p_minifds, const char* key, int key_len, uint8_t* data, length_t length)
{
	key_t TEMP_KEY = 1;
	char rev = 0;
	uint8_t buff[MAX_RECORD_LENGTH];
	printctb(p_minifds);
	if (key_len + length + 1 >= MAX_RECORD_LENGTH)
	{
		DEBUG_LOG_MINIFDS("MINIFDS_ERR_REPEAT_LENGTH \r\n");
		return MINIFDS_ERR_REPEAT_LENGTH;
	}
	memcpy(buff, key, key_len);
	buff[key_len] = ':';
	memcpy(&buff[key_len + 1], data, length);
	rev = minfds_record_find_mem(p_minifds, buff, key_len + 1, &TEMP_KEY);
	if (rev != MINIFDS_SUCCESS)return rev;
	return minfds_record_update(p_minifds, TEMP_KEY, buff, key_len + length + 1);
}

//-----------------------------------------------------------------------------------------------------
/*
extern minfds_t minifds;
void pma_pcs(cli_t *p_cli, unsigned short argc, char **argv)
{
	char keu[]="key1";
	uint8_t datat[]="testdata";
	pm_add(&minifds,keu,sizeof("key1"),datat,sizeof("testdata"));
	minfds_Scan(&minifds);
}
CLI_CMD_REGISTER(pma, "Cli cmd history", pma_pcs);

void pmf_pcs(cli_t *p_cli, unsigned short argc, char **argv)
{
	char keu[]="key1";
	uint8_t datat[50]="11111111111";
	uint8_t length=0;
	pm_find(&minifds,keu,sizeof("key1"),datat,&length);
	 DEBUG_LOG_MINIFDS("%s \r\n",datat);
}
CLI_CMD_REGISTER(pmf, "Cli cmd history", pmf_pcs);

void pmd_pcs(cli_t *p_cli, unsigned short argc, char **argv)
{
	char keu[]="key1";
	uint8_t datat[50]="11111111111";
	pm_delete(&minifds,keu,sizeof("key1"));
	 DEBUG_LOG_MINIFDS("%s \r\n",datat);
}
CLI_CMD_REGISTER(pmd, "Cli cmd history", pmd_pcs);

void pmu_pcs(cli_t *p_cli, unsigned short argc, char **argv)
{
	char keu[]="key1";
	uint8_t datat[50]="11111111111";
	pm_update(&minifds,keu,sizeof("key1"),datat,10);
	 DEBUG_LOG_MINIFDS("%s \r\n",datat);
}
CLI_CMD_REGISTER(pmu, "Cli cmd history", pmu_pcs);

*/












