/************************************************************************/
/* Copyright 2003-2012 MBARI											*/
/************************************************************************/
/* Summary	: Config file routines for BEDS								*/
/* Filename : config.c													*/
/* Author	: Robert Herlien (rah)										*/
/* Project	: BEDS (Benthic Event Detection System)						*/		
/* Revision : 1.0														*/
/* Created	: 10/12/2012												*/
/*																		*/
/* MBARI provides this documentation and code "as is", with no warranty,	*/
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium	*/
/* Research Institute to assist in its use, correction, modification, or	*/
/* enhancement. This information should not be published or distributed to	*/
/* third parties without specific written permission from MBARI.			*/
/*																			*/
/************************************************************************/
/* Modification History:												*/
/* 12oct2012 rah - created												*/
/* $Log$
 */
/************************************************************************/

#include <mbariTypes.h>			/* MBARI type definitions				*/
#include <beds.h>				/* BEDS general definitions				*/		
#include <fatFs/ff.h>			/* FatFs definitions					*/
#include <stdio.h>				/* Standard I/O library					*/
#include <stdlib.h>				/* Standard C library					*/
#include <string.h>				/* Standard string library				*/
#include <ctype.h>				/* Standard ctypes						*/
#include <time.h>
#include <config.h>				/* BEDS configuration					*/
#include <variable.h>			/* Variable function definitions		*/
#include <utils.h>				/* BEDS configuration					*/
#include <fileUtils.h>			/* BEDS file utilities definitions		*/
#include <syslog.h>				/* System logger						*/


/********************************/
/*		External Data			*/
/********************************/

Extern Int32	platformID;
Extern Int32	deploymentID;


/********************************/
/*		Global Data				*/
/********************************/

Global time_t	startTime = 0L;


/********************************/
/*		Module Local Data		*/
/********************************/

MLocal char		cfgBuf[512];
MLocal char		cfgCopy[256];


/************************************************************************/
/* Function	   : parseStartString										*/
/* Purpose	   : Parse "START" line										*/
/* Inputs	   : None													*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
MLocal Errno parseStartString(char *s)
{
	Int32		duration;
	time_t		sttm;
#ifdef DEBUG_TIME
	struct tm	*tmp;
#endif

	deblank(s);
	if ((strncasecmp(s, "AFTER", 5) == 0) && 
		((duration = getDuration(s+6)) >= 0))
		startTime = clkTime() + duration;
	else if ((sttm = getTimespec(s)) > 0)
		startTime = sttm;
	else
		startTime = 0L;
#ifdef DEBUG_TIME
	tmp = gmtime(&startTime);
	printf("START at %d/%d/%d %02d:%02d:%02d\n",
		   tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_year+1900,
		   tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
#endif
	return(OK);

} /* parseStartString() */


/************************************************************************/
/* Function	   : parseConfigLine										*/
/* Purpose	   : Parse one line of BEDS config file						*/
/* Inputs	   : None													*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
MLocal Errno parseConfigLine(char *s)
{
	char		*keyword, *cmdtail, *p;

#ifdef DEBUG_CONFIG
	printf("parseConfigLine(): \"%s\"\r\n", s);
#endif

	keyword = strtok(s, " \t\n\r");
	deblank(keyword);
	cmdtail = s + strlen(keyword) + 1;
	deblank(cmdtail);
#ifdef DEBUG_CONFIG
	printf("parseConfigLine: keyword = \"%s\" cmdtail = \"%s\"\r\n", keyword, cmdtail);
#endif

	if (strcasecmp(keyword, "START") == 0)
		return(parseStartString(cmdtail));

	if (*cmdtail != '=')
		return(ERROR);

	cmdtail++;
	deblank(cmdtail);

	return((setVar(keyword, cmdtail, FALSE) == NULL) ? OK : ERROR);

} /* parseConfigLine() */


/************************************************************************/
/* Function	   : getOneConfigLine										*/
/* Purpose	   : Get one (logical) line from input file					*/
/* Inputs	   : FILE ptr, buffer ptr, buffer len						*/
/* Outputs	   : Number of lines read (>=0) or ERROR					*/
/************************************************************************/
Int32 getOneConfigLine(FIL *fp, char *buf, int buflen)
{
	char		*p;
	Int32		numLines;

	memset(buf, 0, buflen);

	for (numLines = 0; (f_gets(buf, buflen, fp) != NULL); )
	{
		numLines++;
		if ((p = strpbrk(buf, "\n\r")) != NULL)
			*p = '\0';			/* Delete trailing CR, LF, or comment	*/

		p = buf;
		deblank(p);				/* Point to first non-blank char		*/

		if ((*p != '\0') && (*p != '#'))
			return(numLines);	/* If not empty or comment, return		*/

		buf[0] = '\0';			/* Prev was empty, clear buf to start over*/
	}

	return((strlen(buf) > 0) ? numLines : ERROR);

} /* getOneConfigLine() */


/************************************************************************/
/* Function	   : parseConfigFile										*/
/* Purpose	   : Parse the OASIS.CFG file								*/
/* Inputs	   : Name of config file									*/
/* Outputs	   : OK or ERROR											*/
/************************************************************************/
Errno parseConfigFile(char *cfgFileName)
{
	FIL			cfgFp;
	char		*name = CFG_FILE;
	Errno		rtn;

	if (cfgFileName != NULL)
		name = cfgFileName;
  
	if (f_open(&cfgFp, name, FA_READ) != FR_OK)
	{
		printf("Can't open %s\r\n", name);
		return(ERROR);
	}

	while (getOneConfigLine(&cfgFp, cfgBuf, sizeof(cfgBuf)) > 0)
	{
		strncpy(cfgCopy, cfgBuf, sizeof(cfgCopy));
		if ((rtn = parseConfigLine(cfgBuf)) != OK)
		{
			sysLogPrintf("Error parsing \"%s\"", cfgCopy);
			printf("Error parsing \"%s\"\r\n", cfgCopy);
		}
	}

	f_close(&cfgFp);

	checkPlatDepIDs();
	return(OK);

} /* parseConfigFile() */


/************************************************************************/
/* Function	   : dsDepID												*/
/* Purpose	   : Function passed to dirScan to find match on .EVT file	*/
/* Inputs	   : struct dirent from dirScan, ptr to MBool to set		*/
/* Outputs	   : FALSE to stop dirScan (only need 1st conflict)			*/
/************************************************************************/
MLocal MBool dsDepID(FILINFO *de, void *deployOK)
{
	*(MBool *)deployOK = FALSE;
	sysLogPrintf("DeploymentID conflict, file %s", de->fname);
	return(FALSE);
}


/************************************************************************/
/* Function	   : checkPlatDepIDs										*/
/* Purpose	   : Check Platform and Deployment IDs, look for .EVT files */
/* Inputs	   : None													*/
/* Outputs	   : None													*/
/************************************************************************/
void	checkPlatDepIDs(void)
{
	Int32		newDepID;
	MBool		deployOK;
	char		platformChar, nameBuf[32];

	if (platformID <= 0)
		sysLog("WARNING!  Uninitialized Platform ID");

	if (platformID > 35)
		sysLog("WARNING, Platform ID too large");

	if ((deploymentID < 0) || (deploymentID > 255))
	{
		sysLog("WARNING, Deployment ID out of range, setting to 0");
		deploymentID = 0;
	}

	if ((platformID < 0) || (platformID > 35))
		platformChar = '_';
	else if (platformID < 10)
		platformChar = platformID + '0';
	else
		platformChar = platformID - 10 + 'A';


	for (newDepID = deploymentID; newDepID < 255; newDepID++)
	{
		deployOK = TRUE;
		sprintf(nameBuf, "%c%02X?????.EVT", platformChar, (newDepID & 0xff));
		dirScan(nameBuf, dsDepID, &deployOK);

		if (deployOK)
			break;
	}

	deploymentID = newDepID;

	sysLogPrintf("PlatformID = %d, DeploymentID = 0x%x",
		   platformID, deploymentID);
}

