/*
 * CheckTask.c
 *
 *  Created on: 2021年9月22日
 *      Author: 8513
 */
#include <stdio.h>      /*標準輸入輸出定義*/
#include <stdlib.h>     /*標準函數庫定義*/
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <dirent.h>
#include "../Config.h"
#include "../Log/log.h"
#include "../Define/define.h"

#include "../ShareMemory/shmMem.h"
#include "Module_ChkSysTask.h"

struct SysConfigData *pSysConfig = NULL;
struct SysInfoData *pSysInfo = NULL;
struct OCPP16Data *ShmOCPP16Data = NULL;
struct ChargingInfoData *pAcChargingInfo = NULL;
static struct ChargingInfoData *pDcChargingInfo = NULL;
struct SysConfigAndInfo         *ShmSysConfigAndInfo;
struct StatusCodeData           *ShmStatusCodeData;

bool Taskconutstring(char *src, char *taskname)
{
    bool result = false;

    if (src == NULL || strlen(src) == 0)
        return result;

    if (strstr(src, taskname) != NULL &&
        strstr(src, "grep") == NULL &&
        strstr(src, "[") == NULL)
    {
        result = true;
    }

    return result;
}

int GetProcessCount(char *procName)
{
	int result = 0;
	FILE *fp;
	char cmd[256];
	char buf[256];

	sprintf(cmd, "ps -ef |grep %s", procName);
	fp = popen(cmd, "r");
	if(fp != NULL)
	{
		while(fgets(buf, sizeof(buf), fp) != NULL)
		{
			if (Taskconutstring(buf, procName))
				result++;
		}
	}

	pclose(fp);

	return result;
}

unsigned char CheckSystemTask(unsigned char systemPage)
{
	unsigned char result = 0;
	unsigned char count_main 		= GetProcessCount("main");
	unsigned char count_evComm 		= GetProcessCount("Module_EvComm");
	unsigned char count_interComm	= GetProcessCount("Module_InternalComm");
	unsigned char count_eventComm	= GetProcessCount("Module_EventLogging");
	unsigned char count_primaryComm	= GetProcessCount("Module_PrimaryComm");
	unsigned char count_lcmComm	    = GetProcessCount("Module_LcmControl");
	unsigned char count_doComm	    = GetProcessCount("Module_DoComm");
	unsigned char count_produceComm	= GetProcessCount("Module_ProduceUtils");
	unsigned char count_updateFW	= GetProcessCount("Module_UpdateFW");

//	if (systemPage == 0x09 || systemPage == 0x0A)
	{
		if (count_main < _SYSTEM_TASK_COUNT_MAIN )
		{
			system("killall Module_EventLogging");
			system("killall Module_PrimaryComm");
			system("killall Module_EvComm");
			system("killall Module_LcmControl");
			system("killall Module_InternalComm");
			system("killall Module_DoComm");
			system("killall Module_ProduceUtils");
			system("killall Module_UpdateFW");
			system("pkill main");
            sleep(1);
            system("echo V > /dev/watchdog");
			system("/usr/bin/run_evse_restart.sh");
            sleep(10);
		}
		else
		{
			if (count_evComm < _SYSTEM_TASK_COUNT_EVCOMM )
			{
				system("killall Module_EvComm");
				sleep(1);
				system("/root/Module_EvComm &");
			}
        	if (count_interComm < _SYSTEM_TASK_COUNT_INTERNALCOMM )
			{
				system("killall Module_InternalComm");
				sleep(1);
				system("/root/Module_InternalComm &");
			}
			if (count_eventComm < _SYSTEM_TASK_COUNT_EVENTLOGGING )
			{
				system("killall Module_EventLogging");
				sleep(1);
				system("/root/Module_EventLogging &");
			}
			if (count_primaryComm < _SYSTEM_TASK_COUNT_PRIMARYCOMM )
			{
				system("killall Module_PrimaryComm");
				sleep(1);
				system("/root/Module_PrimaryComm &");
			}
			if (count_lcmComm < _SYSTEM_TASK_COUNT_LCM )
			{
				system("killall Module_LcmControl");
				sleep(1);
				system("/root/Module_LcmControl &");
			}
			if (count_doComm < _SYSTEM_TASK_COUNT_DOCOMM )
			{
				system("killall Module_DoComm");
				sleep(1);
				system("/root/Module_DoComm &");
			}
			if (count_produceComm < _SYSTEM_TASK_COUNT_PRODUCEUTILS )
			{
				system("killall Module_ProduceUtils");
				sleep(1);
				system("/root/Module_ProduceUtils &");
			}
			if (count_updateFW < _SYSTEM_TASK_COUNT_UPDATEFW )
			{
				system("killall Module_UpdateFW");
				sleep(1);
				system("/root/Module_UpdateFW &");
			}
		}

	}

	if (count_main < _SYSTEM_TASK_COUNT_MAIN)
		result = _SYSTEM_TASK_LOST_ITEM_MAIN;
	else if (count_evComm < _SYSTEM_TASK_COUNT_EVCOMM)
		result = _SYSTEM_TASK_LOST_ITEM_EVCOMM;
/*	else if (count_psuComm < 2)
		result = 3; */
    else if (count_eventComm < _SYSTEM_TASK_COUNT_EVENTLOGGING )
        result = _SYSTEM_TASK_LOST_ITEM_EVENTLOG;
    else if (count_primaryComm < _SYSTEM_TASK_COUNT_PRIMARYCOMM)
        result = _SYSTEM_TASK_LOST_ITEM_PRIMARYCOMM;
    else if (count_lcmComm < _SYSTEM_TASK_COUNT_LCM)
        result = _SYSTEM_TASK_LOST_ITEM_LCMCONTROL;
    else if (count_interComm < _SYSTEM_TASK_COUNT_INTERNALCOMM )
        result = _SYSTEM_TASK_LOST_ITEM_INTERCOMM;
    else if (count_doComm < _SYSTEM_TASK_COUNT_DOCOMM)
        result = _SYSTEM_TASK_LOST_ITEM_DOCOMM;
    else if (count_produceComm < _SYSTEM_TASK_COUNT_PRODUCEUTILS)
        result = _SYSTEM_TASK_LOST_ITEM_PRODUCTUTILS;
    else if (count_updateFW < _SYSTEM_TASK_COUNT_UPDATEFW)
        result = _SYSTEM_TASK_LOST_ITEM_UPDATEFW;


	return result;
}

//===============================================
// Check System Task alive
// ==============================================
void CheckSystemTaskAlive()
{
    unsigned char lostId = CheckSystemTask(ShmSysConfigAndInfo->SysInfo.SystemPage);
    if (lostId != 0) {
        log_info("Check task(%d) lost\n",lostId);
        if (ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemTaskLost == NO) {
           if (lostId == _SYSTEM_TASK_LOST_ITEM_MAIN)
               log_info("System task lost (CSU). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_EVCOMM)
               log_info("System task lost (EVComm). \n");
//           else if (lostId == _SYSTEM_TASK_LOST_ITEM_PSUCOMM)
//               PRINTF_FUNC("System task lost (PSU Task). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_EVENTLOG)
               log_info("System task lost (Event log). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_PRIMARYCOMM)
               log_info("System task lost (Primary). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_LCMCONTROL)
               log_info("System task lost (LCM Comm). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_INTERCOMM)
               log_info("System task lost (Internal Comm). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_DOCOMM)
               log_info("System task lost (Do Comm). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_PRODUCTUTILS)
               log_info("System task lost (ProcductUtils Comm). \n");
           else if (lostId == _SYSTEM_TASK_LOST_ITEM_UPDATEFW)
               log_info("System task lost (Update FW) \n");
           ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemTaskLost = YES;
        }
    } else
        ShmStatusCodeData->AlarmCode.AlarmEvents.bits.SystemTaskLost = NO;
}


void main(void)
{
    if (CreateAllCsuShareMemory() == FAIL) {
        log_error("create share memory error\r\n");
        return FAIL;
    }

    pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
    pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
    ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
    ShmSysConfigAndInfo = (struct SysConfigAndInfo *)GetShmSysConfigAndInfo();
    ShmStatusCodeData = (struct StatusCodeData *)GetShmStatusCodeData();	
    MappingGunChargingInfo("CheckSystem Task");
    sleep(20);
    while(true)
    {
      	for (uint8_t gun = 0; gun < pSysConfig->TotalConnectorCount; gun++) {
    		pDcChargingInfo = (struct ChargingInfoData *)GetDcChargingInfoData(gun);
			if (pDcChargingInfo->SystemStatus == SYS_MODE_UPDATE )
				continue;
		}
		CheckSystemTaskAlive();
		sleep(3);
    }
}