#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "log_manager_task.h"
#include "Shell_Core.h"
#include "log_creat.h"
#include "shell_core.h"
#include "shell_char.h"
#include "log_bufferappender.h"
#include "printf.h"
#include "shell_cmd.h"

#define LOG_MCU_DATA_MAX   990
#define LOG_BUFFER_OK    0
#define LOG_BUFFER_SAVING    0
#define LOG_BUFFER_FULL     1
#define LOG_SEND_OK     (uint8_t)0
#define LOG_SEND_FAIL   (uint8_t)1u
#define LOG_BUFFER_DATA_MAX   (990-200)
uint8_t log_send_flag = LOG_SEND_OK;
uint32_t log_index = 0;


uint8_t log_mcu_buffer[LOG_MCU_DATA_MAX];

/* 消息队列声明 */
DECLARATION_QUEUE(log_manager_task)


 volatile struct log_buffer_block *dev = (struct log_buffer_block *)LOG_BUF_OFFSET;
 Log_Cfg_t *g_pxLogCfg;
 uint8_t g_ucLogNum = 0;

void vLogInit(void)
{
	g_pxLogCfg = &g_axLog_Cfg[0];
	if(g_axLog_Cfg[0].cfg_size < MAX_BLCOK_NUM)
	{
		g_ucLogNum = g_axLog_Cfg[0].cfg_size;
	}
	else
	{
		g_ucLogNum = MAX_BLCOK_NUM;
		Shell_Printk("[LOG]The number of log modules exceeds 50 [%d]\n",g_axLog_Cfg[0].cfg_size);
	}
	
//	memset((void *)LOG_BUF_OFFSET, 0, LOG_BLK_SIZE);
	vShellTaskStartup();
	vBufferSizeCheck();
}

void log_putc(uint8_t c)
{
	int32_t cache_index = dev->pos_write % LOG_BUFFER_SIZE;
	uint8_t cache_count = 0;

	/* fill 0 at the tail of the buf */
	if (cache_index == LOG_BUFFER_SIZE - 1) {
		dev->addr_buf[LOG_BUFFER_SIZE - 1] = 0;
		cache_index = -1;
		cache_count++;
	}

	dev->addr_buf[cache_index + cache_count++] = c;

	/* fill 0 at the end of the str */
	if (c == '\n') {
		dev->addr_buf[cache_index + cache_count++] = 0;
	}
	dev->pos_write += cache_count;
	
}


void vLogToMem(int level,uint8_t *strtime, const char * fmt, ...)
{
	 static uint8_t new_line = 1;
	 static uint64_t index = 1;
	char buf[512] = {0};
	(void)strtime;
	// uint64_t time = 0;
	int offset = 0;
	
	if (new_line == 1) {
		new_line = 0;
		#if 1
		/* insert index to buf */
		sprintf((char *)buf, "%lld,", index++);
		/* insert timestamp to buf */
		
		//time = GetTimeUs(0);

		offset = strlen((const char *)buf);
		sprintf((char *)(buf+offset), "%lld,", (uint64_t)0);
		//memcpy(buf+offset,strtime,16);
		/* insert level to buf */
		offset = strlen((const char *)buf);
		sprintf((char *)(buf+offset), "%d,", level);
		#endif
	}
	/* insert log to buf */
	va_list ap;
	va_start(ap, fmt);
	offset = strlen(buf);
	vsnprintff(buf+offset, 512-offset, fmt, ap);
	va_end(ap);
	/* put buf into memory */
	

}
#if 0
void mem_printf(int level, const char * fmt, va_list va)
{
	///
	//Shell_Printk("mem_printf\n");
	 static int32_t new_line = 1;
	 static uint64_t index = 1;
	uint8_t buf[128] = {0};
	uint8_t * s;
	
	unsigned long long time = 0;
	int32_t offset = 0;
	if (new_line == 1) {
		new_line = 0;
		/* insert index to buf */
		sprintf((char *)buf, "%lld,", index++);
		/* insert timestamp to buf */
		time =0;
		offset = strlen((char *)buf);
		sprintf((char *)(buf+offset), "%lld,", time);
		/* insert level to buf */
		offset = strlen((char *)buf);
		sprintf((char *)(buf+offset), "%d,", level);
	}
	/* insert log to buf */
	offset = strlen((char *)buf);
	//vsnprintf(buf+offset, 128-offset, fmt, va);
	vsnprintff(buf+offset, 128-offset, fmt, va);
	/* put buf into memory */
	s = buf;
	//Shell_Printk("STR:%s\r\n",s);
	while(*s) {
		if (*s == '\n') 
		{
			new_line = 1;
		}
		log_putc(*s++);
	}		
}
#endif
uint8_t Log_buffer_cnt = 0;
uint8_t McuLogGet_Check(void)
{
	uint8_t logGetBuf[200] = {0};
	Log_Buffer_Param *log_cfg; 
	uint16_t dataLength = 0;
	uint8_t ret = LOG_BUFFER_SAVING;
	static uint32_t time = 0;
	
	(void)memset(&log_cfg,0,sizeof(log_cfg));
	if((time == 100))
	{
		time = 0;
		
		if(log_index != 0)
		{
			return LOG_BUFFER_FULL;	
		}
	}
	else
	{
		time++;
		while (Log_buffer_cnt < g_ucLogNum)
		{
			memset(&logGetBuf[0],0,sizeof(logGetBuf));

			if(g_pxLogCfg->log_cfg != NULL)
			{
				log_cfg = &g_pxLogCfg->log_cfg[Log_buffer_cnt];
			}
			if((log_cfg != NULL) && ((uint8_t*)log_cfg->logname != NULL))
			{
				if(log_index < LOG_BUFFER_DATA_MAX)
				{
					dataLength = usLog_RB_MCU_GetOne(logGetBuf, (sizeof(logGetBuf) - 1),Log_buffer_cnt);
					if(dataLength > 0)
					{
						memcpy(&log_mcu_buffer[log_index],logGetBuf,dataLength);
						log_index = log_index + dataLength;
					}
				}
				else
				{
					time = 0;
					return LOG_BUFFER_FULL;
				}
			}
			Log_buffer_cnt++;
		}
		if(Log_buffer_cnt >= g_ucLogNum )
		{
			Log_buffer_cnt = 0;
		}
	}

	return ret;
}
static void vLogSendToMCU(void)
{
	uint8_t ret;
	uint8_t status = LOG_BUFFER_OK;
	
	if(log_send_flag == LOG_SEND_OK)
	{
		status = McuLogGet_Check();		
	}
	if((status == LOG_BUFFER_FULL)||(log_send_flag == LOG_SEND_FAIL))
	{		
		//ret = IPC_SWC_EC2VP_LOG_message_info_Server(255,log_mcu_buffer,LOG_MCU_DATA_MAX);	
		if (ret == 0)
		{
			log_send_flag = LOG_SEND_OK;
			log_index = 0;
			memset(log_mcu_buffer,0,sizeof(log_mcu_buffer));
		}
		else
		{
			log_send_flag = LOG_SEND_FAIL;
			
		}		
	}
}




void TASK_FUNC(log_manager_task)( void *pvParameters )
{
    //uint32 Index;
    //base_t ret;
    //msg_buffer_t mbuffer[16];
    //CMsg_t recvMsg;
	(void)pvParameters;
    for( ;; )
    {
			
		vShellMainProcStep();
		vCycleGetDebugCmd();
		
		//vLogSendToMCU(); /*Do not know who to send, temporarily blocked*/
		vEchoBufferClear();

        vTaskDelay(pdMS_TO_TICKS(20));
    }
}