#include 	<sys/time.h>
#include 	<sys/timeb.h>
#include  	<sys/types.h>
#include  	<sys/stat.h>
#include 	<sys/types.h>
#include 	<sys/ioctl.h>
#include 	<sys/socket.h>
#include 	<sys/ipc.h>
#include 	<sys/shm.h>
#include 	<sys/shm.h>
#include 	<sys/mman.h>
#include 	<linux/wireless.h>
#include 	<arpa/inet.h>
#include 	<netinet/in.h>

#include 	<unistd.h>
#include 	<stdarg.h>
#include  	<stdio.h>
#include  	<stdlib.h>
#include  	<unistd.h>
#include  	<fcntl.h>
#include  	<termios.h>
#include 	<errno.h>
#include 	<errno.h>
#include 	<string.h>
#include	<time.h>
#include	<ctype.h>
#include 	<ifaddrs.h>
#include 	<math.h>
#include	"define.h"
#include	"main.h"


#define ARRAY_SIZE(A)		(sizeof(A) / sizeof(A[0]))
#define PASS				1
#define FAIL				0
#define ON					1
#define OFF					0


struct SysConfigAndInfo			*ShmSysConfigAndInfo;
struct StatusCodeData 			*ShmStatusCodeData;
struct OCPP16Data				*ShmOCPP16Data;
struct OCPP20Data				*ShmOCPP20Data;
struct Charger					*ShmCharger;

int StoreLogMsg(const char *fmt, ...)
{
	char Buf[4096+256];
	char buffer[4096];
	time_t CurrentTime;
	struct tm *tm;
	struct timeval tv;
	va_list args;

	va_start(args, fmt);
	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
	va_end(args);

	memset(Buf,0,sizeof(Buf));
	CurrentTime = time(NULL);
	tm=localtime(&CurrentTime);
	gettimeofday(&tv, NULL); // get microseconds, 10^-6

	sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d.%06ld]%s\" >> /Storage/SystemLog/[%04d.%02d]Module_DebugLog",
				tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec,
				buffer,
				tm->tm_year+1900,tm->tm_mon+1);

#ifdef SystemLogMessage
	system(Buf);
#endif

#ifdef ConsloePrintLog
	printf("[%04d.%02d.%02d %02d:%02d:%02d.%06ld]%s", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,tv.tv_usec, buffer);
#endif

	return rc;
}

int InitShareMemory()
{
	int result = PASS;
	int MeterSMId;

	//Initial ShmSysConfigAndInfo
	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("[shmat ShmSysConfigAndInfo NG\n");
		#endif
		result = FAIL;
	}

	//Initial ShmStatusCodeData
	if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
		#endif
		result = FAIL;
	}
	else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
		#endif
		result = FAIL;
	}

	// Initial ShmOCPP16Data
	if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0)
	{
		DEBUG_ERROR("shmget ShmOCPP16Data NG\n");
		result = FAIL;
	}
	else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		DEBUG_ERROR("shmat ShmOCPP16Data NG\n");
		result = FAIL;
	}

	// Initial ShmOCPP20Data
	if ((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), 0777)) < 0)
	{
		DEBUG_ERROR("shmget ShmOCPP20Data NG\n");
		result = FAIL;
	}
	else if ((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		DEBUG_ERROR("shmat ShmOCPP20Data NG\n");
		result = FAIL;
	}

	//Initial ShmCharger
	if ((MeterSMId = shmget(ShmChargerKey, sizeof(struct Charger), 0777)) < 0)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmget ShmChargerKey NG\r\n");
		#endif
		result = FAIL;
	}
	else if ((ShmCharger = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("shmat ShmChargerKey NG\r\n");
		#endif
		result = FAIL;
	}

	return result;
}

void wait()
{
	printf("\n Please press any key then \"Enter\" to continue.");
	while(getchar() =='\n') usleep(100000);
}

int main(void)
{
	char cmd[128];

	if(InitShareMemory() == FAIL)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("InitShareMemory NG\n");
		#endif
		if(ShmStatusCodeData!=NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
		}
		sleep(5);
		return 0;
	}
	else
	{
		DEBUG_INFO("InitShareMemory OK.\r\n");
	}

	for(;;)
	{
		system("clear");
		memset(cmd, 0x00, ARRAY_SIZE(cmd));
		printf("\n ============== Debug main menu ==================");
		printf("\n  info: List charger status info.");
		printf("\n  test: Charger test command.");
		printf("\n  exit: Exit Module_Debug_Test.");
		printf("\n =================================================");
		printf("\n  Please input debug command: ");
		scanf("%s", &cmd[0]);

		if(strcmp(cmd, "info") == 0)
		{
			uint8_t isExit = FALSE;
			int gun_index;

			do
			{
				system("clear");
				memset(cmd, 0x00, ARRAY_SIZE(cmd));
				printf("\n ***************** Info menu *********************");
				printf("\n  csu: charger info");
				printf("\n  mcu: mcu request state");
				printf("\n  exit: exit to previous menu.");
				printf("\n *************************************************");
				printf("\n  Please input info need to query: ");
				scanf("%s", &cmd[0]);

				if(strcmp(cmd, "csu") == 0)
				{
					printf("\n  Please input gun index: ");
					scanf("%d", &gun_index);
					printf("\n CSU info.\n\n");

					gun_index = gun_index<AC_QUANTITY?gun_index:0;

					printf("\n  CSU u-boot version: %s", ShmSysConfigAndInfo->SysInfo.CsuBootLoadFwRev);
					printf("\n  CSU kernel version: %s", ShmSysConfigAndInfo->SysInfo.CsuKernelFwRev);
					printf("\n  CSU rootfs version: %s", ShmSysConfigAndInfo->SysInfo.CsuRootFsFwRev);
					printf("\n --------------------------------------------------");
					printf("\n  Charger connector plug times: %d", ShmCharger->gun_info[gun_index].gunPluginTimes.GunPluginTimes);
					printf("\n --------------------------------------------------");
					printf("\n  CP positive voltage: %.2f", ShmCharger->gun_info[gun_index].PilotVoltage.PilotVoltagePositive);
					printf("\n  CP negative voltage: %.2f", ShmCharger->gun_info[gun_index].PilotVoltage.PilotVoltageNegative);
					printf("\n --------------------------------------------------");
					printf("\n  CSU to MCU legacyRequest: %d", ShmCharger->gun_info[gun_index].legacyRequest.isLegacyRequest);
					printf("\n  CSU to MCU relay on request: %d", ShmCharger->gun_info[gun_index].legacyRequest.isRelayOn);
					printf("\n --------------------------------------------------");
					printf("\n  Charger charging mode BS/HLC: %d", ShmCharger->gun_info[gun_index].chargingMode);
					printf("\n --------------------------------------------------");
					printf("\n  Charger input voltage L1: %.2f", ShmCharger->gun_info[gun_index].inputVoltage.L1N_L12);
					printf("\n --------------------------------------------------");
					printf("\n  CSU output current L1: %.2f", ShmCharger->gun_info[gun_index].outputCurrent.L1N_L12[0]);
					printf("\n --------------------------------------------------");
					printf("\n  CSU power total consumption: %.2f", (ShmCharger->gun_info[gun_index].powerConsumption.power_consumption/100.0));
					printf("\n --------------------------------------------------");
					printf("\n  CSU temperature: %d", ShmCharger->gun_info[gun_index].temperature.point[0]);

					wait();
				}
				else if(strcmp(cmd, "mcu") == 0)
				{
					printf("\n  Please input gun index: ");
					scanf("%d", &gun_index);
					printf("\n  MCU info.\n\n");

					gun_index = gun_index<AC_QUANTITY?gun_index:0;

					printf("\n  Firmware version: %s", ShmCharger->gun_info[gun_index].ver.Version_FW);

					wait();
				}
				else if(strcmp(cmd, "exit") == 0)
				{
					printf("\n  Exit to previous.\n\n");
					isExit = TRUE;
				}
			}while(!isExit);
		}
		else if(strcmp(cmd, "test") == 0)
		{
			int gun_index;

			memset(cmd, 0x00, ARRAY_SIZE(cmd));
			printf("\n ***************** Info menu *********************");
			printf("\n  start: start charging session");
			printf("\n  stop: stop charging session");
			printf("\n  operative: enable charger gun");
			printf("\n  inoperative: disable charger gun");
			printf("\n  exit: exit to previous menu.");
			printf("\n *************************************************");
			printf("\n  Please input command: ");
			scanf("%s", &cmd[0]);

			if(strcmp(cmd, "start") == 0)
			{
				printf("\n  Please input gun index: ");
				scanf("%d", &gun_index);

				ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].schedule.isTriggerStart = ON;
			}
			else if(strcmp(cmd, "stop") == 0)
			{
				printf("\n  Please input gun index: ");
				scanf("%d", &gun_index);

				ShmSysConfigAndInfo->SysInfo.AcChargingData[gun_index].schedule.isTriggerStop = ON;
			}
			else if(strcmp(cmd, "operative") == 0)
			{
				printf("\n  Please input gun index: ");
				scanf("%d", &gun_index);

				if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
				{
					sprintf((char*)ShmOCPP16Data->ChangeAvailability[gun_index].Type, "Operative");
					ShmOCPP16Data->CsMsg.bits[gun_index].ChangeAvailabilityReq = ON;
				}
				else
				{
					sprintf((char*)(char*)ShmOCPP20Data->ChangeAvailability[gun_index].operationalStatus, "Operative");
					ShmOCPP20Data->CsMsg.bits[gun_index].ChangeAvailabilityReq = ON;
				}
			}
			else if(strcmp(cmd, "inoperative") == 0)
			{
				printf("\n  Please input gun index: ");
				scanf("%d", &gun_index);

				if(ShmSysConfigAndInfo->SysInfo.OcppRunningVer == OCPP_RUNNING_VERSION_16)
				{
					sprintf((char*)ShmOCPP16Data->ChangeAvailability[gun_index].Type, "Inoperative");
					ShmOCPP16Data->CsMsg.bits[gun_index].ChangeAvailabilityReq = ON;
				}
				else
				{
					sprintf((char*)(char*)ShmOCPP20Data->ChangeAvailability[gun_index].operationalStatus, "Inoperative");
					ShmOCPP20Data->CsMsg.bits[gun_index].ChangeAvailabilityReq = ON;
				}
			}
			else if(strcmp(cmd, "exit") == 0)
			{
				printf("\n  Exit to previous.\n\n");
			}
		}
		else if(strcmp(cmd, "exit") == 0)
		{
			printf("\n  exit program.\n\n");
			return FAIL;
		}
	}

	return FAIL;
}