/*
* FileName:shell_core.c
* Author : qiuxf
* CreateTime: 18-8-7 14:09
* Description:
*/
/**
@file shell_core.c
@brief Shell core process.
*/

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


/********************************************************************************************
Include File Section
********************************************************************************************/
#include "shell_mem.h"
#include "shell_char.h"
#include "log.h"
#include "shell_cmd.h"
#include "string.h"
#include "shell_inode.h"
#include "shell_file.h"
#include "main.h"
//#include "task_init.h"
#include "shell_port.h"
#include "shell_core.h"
#include "log.h"
#include "log_bufferappender.h"
/********************************************************************************************
Macro Definition Section
********************************************************************************************/
#define LOGCAT_HELP_OUTPUT		"/*logcat start *more information please use logcat help */"	

/********************************************************************************************
Prototype Declaration Section
********************************************************************************************/
SHELL_STATUS xShellCyclicTaskletSet(SHELL_CYCLIC_TASKLET *tasklet,uint8_t buffID);
void vShellCyclicTaskletClr(void);
SHELL_STATE xShellGetStatus(void);
void vShellSetStatus(SHELL_STATE statu);
void vShellSetAuthor(SHELL_AUTHOR newAuthor);
SHELL_AUTHOR xShellGetAuthor(void);
void vShellWriteHead(void);
void vShellCmdProcess(SHELL_MSG_GROUP *pmsg);
void vShellCyclicTasklet(void);
void vShellTaskStartup(void);
void vShellReceiveCharProcess(uint8_t recvChar);
void vShellMainProcStep(void);

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

/********************************************************************************************
Global Variable Definition Section
********************************************************************************************/
// QM_DATA uint8_t g_ucVersionCheck = 0;
/********************************************************************************************
Static Variable Definition Section
********************************************************************************************/
static SHELL_STATE s_xShellStatus = SHELL_IDLE;
static SHELL_AUTHOR s_xShellAuthor = AUTHOR_USER;
static SHELL_CYCLIC_TASKLET s_xShellCyclicTask;




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


/********************************************************************************************
Function Definition Section
********************************************************************************************/
/**
 * xShellCyclicTaskletSet
 * Author qiuxf
 * @param none
 * @return none
*/
SHELL_STATUS xShellCyclicTaskletSet(SHELL_CYCLIC_TASKLET *tasklet,uint8_t buffID)
{
	 s_xShellCyclicTask.p_arg = tasklet->p_arg;
	 s_xShellCyclicTask.buffID = buffID;
	 s_xShellCyclicTask.proc = tasklet->proc;
	 s_xShellCyclicTask.endproc = tasklet->endproc;
	 return PROC_SUCESS;
}

 /**
  * vShellCyclicTaskletClr
  * Author qiuxf
  * @param none
  * @return none
  */
void vShellCyclicTaskletClr(void)
{
	 s_xShellCyclicTask.buffID =0xFF;
	 s_xShellCyclicTask.proc = SAF_NULL;
	 s_xShellCyclicTask.p_arg = SAF_NULL;
}

/**
 * xShellGetStatus
 * Author qiuxf
 * @param none
 * @return none
 */
SHELL_STATE xShellGetStatus(void)
{
    return s_xShellStatus;
}

/**
* vShellSetStatus
* Author qiuxf
* @param none
* @return none
*/
void vShellSetStatus(SHELL_STATE statu)
{
    s_xShellStatus = statu;
}

/**
* vShellSetAuthor
* Author qiuxf
* @param none
* @return none
*/
void vShellSetAuthor(SHELL_AUTHOR newAuthor)
{
    s_xShellAuthor = newAuthor;
}

/**
* xShellGetAuthor
* Author qiuxf
* @param none
* @return none
*/
SHELL_AUTHOR xShellGetAuthor(void)
{
    //return s_xShellAuthor;
	return AUTHOR_USER;
}

void vShellWriteHead(void)
{
	if(xShellGetAuthor() == AUTHOR_ROOT)
	{
		vShellWriteRootHead();
	}
	else
	{
		vShellWriteUserHead();
	}
}
/**
* vShellCmdProcess
* Author qiuxf
* @param pmsg
* @return none
*/
void vShellCmdProcess(SHELL_MSG_GROUP *pmsg)
{
    const uint8_t *cmd = SAF_NULL;
    const SHELL_CMD *pCmd = SAF_NULL;
    const uint8_t *argv[SHELL_MAX_ARGC];
    uint8_t ret = SAF_FALSE;

    if(0 != pmsg->argc)
    {
		cmd = pmsg->argv[0];
		for(uint32_t i = 1; i < pmsg->argc; i++)
		{
			argv[i - 1] = (const uint8_t *)&pmsg->argv[i];
		}
		pCmd = pxShellGetCmdFromTbl(cmd);
		if(pCmd != SAF_NULL)
		{
			if(s_xShellAuthor == AUTHOR_ROOT)
			{
				/*execute all command*/
				ret = pCmd->CmdFunc(pmsg->argc - 1, argv);
			}
			else
			{
				if(s_xShellAuthor == pCmd->author)
				{
					ret = pCmd->CmdFunc(pmsg->argc - 1, argv);
				}
			}
		}
		else
		{
			UART_WRITE_STR("Can Not Find Command\r\n");
			vShellWriteHead();
		}
		if(SAF_FALSE == ret)
		{
			vShellSetStatus(SHELL_IDLE);
		}
	}
}

/**
* vShellCyclicTasklet
* Author qiuxf
* @param none
* @return none
*/
void vShellCyclicTasklet(void)
{
	uint8_t reslt = SAF_FALSE;

	if(SAF_NULL != s_xShellCyclicTask.proc)
	{
		if(CTRL_INIT ==  xShellCtrlGet())
		{
			s_xShellCyclicTask.proc(s_xShellCyclicTask.p_arg, &reslt,s_xShellCyclicTask.buffID);
			if(SAF_FALSE == reslt)
			{
				/*call end*/
				if(SAF_NULL != s_xShellCyclicTask.endproc)
				{
					s_xShellCyclicTask.endproc(s_xShellCyclicTask.p_arg,s_xShellCyclicTask.buffID);
				}
				vShellCyclicTaskletClr(); //stop process
				s_xShellStatus = SHELL_IDLE;
			}
		}
		else
		{
			/*singnal kill */
			if(SAF_NULL != s_xShellCyclicTask.endproc)
			{
				s_xShellCyclicTask.endproc(s_xShellCyclicTask.p_arg,s_xShellCyclicTask.buffID);
			}
			vShellCyclicTaskletClr();

			printk("SIGNAL KILL\r\n");
			vShellWriteHead();//write head
			s_xShellStatus = SHELL_IDLE;
		}
	}
	else
	{
		; /*do nothing*/
	}
}

/**
 * vShellTaskStartup
 * Author qiuxf
 * @param p_arg     task arg
 * @return none
 * @description main function for shell
 */

void vShellTaskStartup(void)
{
	/*init timer*/
	//Ecarx_TimerQueueInit();
    /*init uart*/
	
    vShellPortInit();
   //Buffer_Size_Check();
    /*init file system*/
    vShellInodeInit();
    xShellFileMemCreate();
	lModeLogInodeInit();
}


void vShellReceiveCharProcess(uint8_t recvChar)
{
	SHELL_MSG_GROUP *pMsg = SAF_NULL;
	if(SAF_TRUE == ucShellCharIntProc(recvChar))
	{
		s_xShellStatus = SHELL_BUSY;
		vShellCtrlSet(CTRL_INIT);
		pMsg = pxShellGetMsgGroup();
		if(0 != pMsg->argc)
		{
			vShellCmdProcess(pMsg);
		}
		else
		{
			; /*do nothing*/
		}
		vShellClearMsgBuf();
	}
}
/*
 * Shell_MainFunction
 * Author qiuxf
 * @param p_arg     task arg
 * @return none
 * @description main function for shell
 */
void vShellMainProcStep(void)
{
    /*Task Local varib*/
	static uint8_t s_ucWriteHeadFlag = 0;
    uint8_t recvChar = 0;
    uint8_t retRecvChar = SAF_FALSE;
	uint8_t updownchar[3] = {0};

	if(0 == s_ucWriteHeadFlag)
	{
		s_ucWriteHeadFlag = 1;
		vShellWriteHead();
	}
	retRecvChar = lShellPortGetChar(UART_COM,(uint8_t *)&recvChar);
	if(SAF_TRUE == retRecvChar)
	{
		if(recvChar == '[')
		{
			updownchar[0] = recvChar;
			retRecvChar = lShellPortGetChar(UART_COM,(uint8_t *)&recvChar);
			if(SAF_TRUE == retRecvChar)
			{
				if(recvChar == 'A')
				{
					vShellKeyUp();
				}
				else if(recvChar == 'B')
				{
					vShellKeyDown();
				}
				else
				{
					vShellReceiveCharProcess(updownchar[0]);
					vShellReceiveCharProcess(recvChar);
				}
			}
			else
			{
				vShellReceiveCharProcess(recvChar);
			}
		}
		else
		{
        	vShellReceiveCharProcess(recvChar);
		}
	}
	/*Cyclic method*/
	vShellCyclicTasklet();
}
