
/**
@file log_category.c
@brief Log data parsing.
*/

/********************************************************************************************
Debug Switch Definition Section
********************************************************************************************/


/********************************************************************************************
Include File Section
********************************************************************************************/
#include <stdlib.h>
#include "ecarx_queue.h"
#include "shell_char.h"
#include "log_event.h"
#include "log_filter.h"
#include "log_appender.h"
#include "log_simplefilter.h"
#include "log_layout.h"
#include "log_simplelayout.h"
//#include "delay.h"
#include "log_bufferappender.h"
#include "log_category.h"

/********************************************************************************************
Macro Definition Section
********************************************************************************************/

/********************************************************************************************
Prototype Declaration Section
********************************************************************************************/
void vCatgoryConstruct(LOG_CATEGORY *category);
static uint8_t ucMakeLogEvent(LoggingEvent *ptevent, const uint8_t *cateName, int32_t pri, const uint8_t *format, va_list va);
static void vDoAppender(LOG_CATEGORY *category, LoggingEvent *ptevent);
 void vLOG_DEBUG(LOG_CATEGORY *category, const uint8_t *format, ...);
uint64_t getCurrentTime(void);


/********************************************************************************************
Const Global Variable Definition Section
********************************************************************************************/


/********************************************************************************************
Global Variable Definition Section
********************************************************************************************/


/********************************************************************************************
Static Variable Definition Section
********************************************************************************************/


/********************************************************************************************
Structure Type Definition Section
********************************************************************************************/


/********************************************************************************************
Function Definition Section
********************************************************************************************/
static uint64_t previous_ticks = 0;
static uint64_t overflow_count = 0;

uint64_t getCurrentTime()
{
    uint32_t current_ticks = Stm_Ip_GetCounterValue(0);
	uint64_t total_ticks = 0;
    if (current_ticks < previous_ticks)
    {
        // Overflow detected
        overflow_count++;
    }
    previous_ticks = current_ticks;
    total_ticks = ((uint64_t)current_ticks) + overflow_count * ((uint64_t)UINT32_MAX+1);
    return total_ticks / 300;  // Convert ticks to milliseconds
}

/**
@brief Catgory Construct
@param category [in] category
@return void
*/
void vCatgoryConstruct(LOG_CATEGORY *category)
{
	(void)category;
    if(xAppender.open != SAF_NULL)
    {
        xAppender.open(&xAppender);
    }
    else
    {
        Shell_Printk("[LOG]Appender open is empty\r\n");
    }
    return;
}
/**
 * ucMakeLogEvent
 * Author qiuxf
 * @param priority
 * @return status
 */
static uint8_t ucMakeLogEvent(LoggingEvent *ptevent, const uint8_t *cateName, int32_t pri, const uint8_t *format, va_list va)
{
    uint8_t ret = SAF_TRUE;

    ptevent->categoryName = cateName;
    ptevent->priority = pri;
   	ptevent->timeStamp = getCurrentTime();
    if(0 < vsnprintf(ptevent->message, sizeof(ptevent->message), (const char *)format, va))
    {
        ret = SAF_TRUE;
    }
    else
    {
        ret = SAF_FALSE;
    }
    return ret;
}

/**
 * vDoAppender
 * Author qiuxf
 * @param priority
 * @return status
 */
static void vDoAppender(LOG_CATEGORY *category, LoggingEvent *ptevent)
{
    
    if((category->prority_gate) >= (ptevent->priority))
    {

	    if(xAppender.doappend!=SAF_NULL)
	    {
	        xAppender.doappend(&xAppender, ptevent);
	    }
	    else
	    {
	        Shell_Printk("[LOG]Appender doappend is empty\r\n");
	    }
    }
	else
	{
		Shell_Printk("[LOG]vDoAppender fail\r\n");
	}
}


/**
 * DEBUG
 * Author qiuxf
 * @param priority
 * @return status
 */
 void vLOG_DEBUG(LOG_CATEGORY *category, const uint8_t *format, ...)
{
    LoggingEvent event;
	va_list va;
    if (xSemaphoreTake(LogMutexInput, portMAX_DELAY) == pdTRUE) 
	{
	    if(category != SAF_NULL)
	    {
	        if(CATE_UNINITED == category->init_flag)
	        {
	            vCatgoryConstruct(category);
	            category->init_flag = CATE_INITED;
	        }
	        ///vSignCheck(format);
	        va_start(va, format);
	        if(SAF_TRUE == ucMakeLogEvent(&event, category->name, DEBUG, format, va))
	        {
	        
	            vDoAppender(category, &event);
	        }
	        else
	        {
	            Shell_Printk("[LOG]make log event fail ");
	        }
	        va_end(va);
	    }
	    else
	    {
	        Shell_Printk("[LOG]Input function error\r\n");
	    }  
		xSemaphoreGive(LogMutexInput);
    }
	else
    {
		Shell_Printk("[LOG]mutex take fail \r\n");
	}
}




