/****************************************************************************/
/* Copyright 2012-2018 MBARI												*/
/****************************************************************************/
/* Summary	: Command processor for BEDS2 on PIC32MX470						*/
/* Filename : bedsUI.c														*/
/* Author	: Robert Herlien (rah)											*/
/* Project	: BEDS (Benthic Event Detection System)							*/
/* Revision : 1.0															*/
/* Created	: 09/17/2012													*/
/****************************************************************************/
/* Modification History:													*/
/* 17sep2012 rah - created from Persistor "toPico" stationery and			*/
/*				   previous BEDS prototypes									*/
/* 28feb2019 rah - Ported to PIC32MX470										*/
/****************************************************************************/


#include <mbariTypes.h>			/* MBARI type definitions				*/
#include <beds.h>				/* BEDS general definitions				*/
#include <dig_io.h>				/* BEDS digital I/O definitions			*/
#include <bedsUI.h>				/* BEDS Command line processor			*/
#include <bedsCmd.h>			/* BEDS user function definitons		*/
#include <bedsCmdTbl.h>			/* BEDS Command table					*/
#include <clock.h>				/* BEDS Clock module					*/
#include <fatFs/ff.h>			/* FatFs definitions					*/
#include <syslog.h>				/* System logger						*/
#include <utils.h>				/* BEDS Utility routines				*/
#include <watch.h>				/* BEDS watch cycle						*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>


/************************************/
/*		External Data				*/
/************************************/

Extern Int32	modemPort;				/* Modem port					*/
Extern Int32	modemBaud;				/* Baud rate on SCI port		*/
Extern Int32	debugBaud;				/* Baud rate on TPU port		*/


/************************************/
/*		Module Local Data			*/
/************************************/

MLocal char		cmdBuf[CMDBUF_LEN];
MLocal char		argBuf[CMDBUF_LEN];
MLocal char		*argvBuf[NARGS];


/************************************************************************/
/* Function	   : executeCmdLine											*/
/* Purpose	   : Execute the given command line (from user)				*/
/* Inputs	   : Command Line ptr										*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn executeCmdLine(char *cmdLine)
{
	Reg const CmdEntry	*cp;
	Reg Nat32			argc, i;
	Reg char			*p;

	/* Parse argc, argv			*/
	memset(argBuf, 0, sizeof(argBuf));
	memset(argvBuf, 0, sizeof(argvBuf));
	memcpy(argBuf, cmdLine, sizeof(argBuf));

	for (argc = 0, p = argBuf; (argc < NARGS) && *p; )
	{
		argvBuf[argc] = p;
		while (*p && !isspace(*p))
			p++;

		*p++ = '\0';
		argc++;
		
		while(*p && isspace(*p))
			p++;
	}

	serRxFlush(getConsole());

	for (i = 0, cp = cmdTbl; i < NumberOf(cmdTbl); i++, cp++)
	{									/* Find command table entry		*/
		if (strcasecmp(cp->cmdName, argvBuf[0]) == 0)
		{
			return((*cp->cmdFunc)(argc, argvBuf));
		}
	}

	return(CMD_NOT_FOUND);

} /* executeCmdLine() */


/************************************************************************/
/* Function	   : runUI													*/
/* Purpose	   : Run the (modified PicoDOS) user interface				*/
/* Inputs	   : Initial privilege level for UI commands				*/
/* Outputs	   : None													*/
/* Comments	   : Runs on serial port set up via setConsole() in serial.c*/
/*				 Runs until user quit or timeout						*/
/************************************************************************/
void runUI(SerPort port)
{
	int			getsRtn;
	CmdEntry	*cp;
	CmdRtn		rtn;
	char		cwdBuf[32];

	if (port > PIC_UARTS)
		return;

	setConsole(port);
	setSerialBaud(port, (port == modemPort) ? modemBaud : debugBaud);

	sensorsOn(MODEM_SAMPLING);
	sysLogPrintf("Running User I/F on port %d", port);

	while(TRUE)
	{
		memset(cmdBuf, 0, sizeof(cmdBuf));

		if (f_getcwd(cwdBuf, sizeof(cwdBuf)) != FR_OK)
			cwdBuf[0] = '\0';

		printf("\r\nBEDS)%s>", cwdBuf);

		getsRtn = gets_lpt(cmdBuf, sizeof(cmdBuf));

		if (getsRtn == TMOUT)
		{
			printf("\r\nTIMEOUT\r\n");
			sysLog("Command parser TIMEOUT");
			sensorsOff(MODEM_SAMPLING);
			return;
		}
		else if (getsRtn)
		{
			newline();
			rtn = executeCmdLine(cmdBuf);

			if (rtn == ABORT)
			{
				sensorsOff(MODEM_SAMPLING);
				return;
			}
			else if (rtn == CMD_NOT_FOUND)
				printf("\r\nCommand Not Found\r\n");

			else if (rtn != OK)
				printf("\r\nCommand Error\r\n");
		}
	}

} /* runUI() */


/************************************************************************/
/* Function	   : helpCmd												*/
/* Purpose	   : User Help Function										*/
/* Inputs	   : argc, argv												*/
/* Outputs	   : OK														*/
/* Comments	   : Placed here, rather than in bedsCmd.c, because it needs*/
/*				 access to the user function table						*/
/************************************************************************/
CmdRtn helpCmd(int argc, char **argv)
{
	Reg Nat32		i;
	Reg const CmdEntry	*cp;

	for (i = 0, cp = cmdTbl; i < NumberOf(cmdTbl); i++, cp++)
	{
		if ((argc <= 1) || (strncasecmp(cp->cmdName, argvBuf[0], strlen(cp->cmdName)) == 0))
			if (cp->cmdHelp != NULL)
				printf("%-12s %s\r\n", cp->cmdName, cp->cmdHelp);
	}

	return( OK );

} /* help() */


/************************************************************************/
/* Function	   : cmdTest												*/
/* Purpose	   : TEST command											*/
/* Inputs	   : Command Line ptr										*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
CmdRtn cmdTest(int argc, char **argv)
{
	int		i, opt;
	int		a=0, A=0, b=0, c=0, d=0;

	printf("argc = %d, argv's: \r\n", argc);

	for (i = 0; i < argc; i++)
		printf("%s\r\n", argv[i]);

    while ((opt = getopt(argc, argv, "aA:bc:d")) != -1)
	{
        switch (opt)
		{
		  case 'a': a=1; break;
		  case 'A': A=atoi(optarg); break;
		  case 'b': b=1; break;
		  case 'c': c=atoi(optarg); break;
		  case 'd': d=1; break;
		  default: printf("getopt() returns %c\r\n", opt);
		}
	}

	printf("\r\nAfter getopt() loop\r\n");
	printf("a = %d, A = %d, b = %d, c = %d, d = %d\r\n", a, A, b, c, d);
	printf("optind = %d\r\n", optind);

	printf("argc = %d, argv's: \r\n", argc);

	for (i = 0; i < argc; i++)
		printf("%s\r\n", argv[i]);

	return(OK);
}
