/************************************************************************/
/* 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 <mbariConst.h>		/* MBARI constants			*/
#include <cfxpico.h>		/* Persistor PicoDOS Definitions	*/
#include <beds.h>		/* BEDS general 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 <dirent.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		*/
/********************************/

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 = time(&sttm) + duration;
    else if ((sttm = getTimespec(s)) > 0)
	startTime = sttm;
    else
	startTime = 0L;
#ifdef DEBUG_TIME
    tmp = gmtime(&startTime);
    printf("START at %ld/%ld/%ld %02ld:%02ld:%02ld\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
    cprintf("parseConfigLine(): \"%s\"\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\"\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(FILE *fp, char *buf, int buflen)
{
    char	*p;
    Int32	numLines;

    memset(buf, 0, buflen);

    for (numLines = 0; (fgets(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)
{
    FILE	*cfgFp;
    char	*name = CFG_FILE;
    Errno	rtn;

    if (cfgFileName != NULL)
	name = cfgFileName;
  
    if ((cfgFp = fopen(name, "r")) == NULL)
    {
	printf("Can't open %s\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\"\n", cfgCopy);
	    cprintf("Error parsing \"%s\"\n", cfgCopy);
	}
    }

    CIOdrain();
    fclose(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(struct dirent *de, MBool *deployOK)
{
    *deployOK = FALSE;
    sysLogPrintf("DeploymentID conflict, file %s\n", de->d_name);
    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\n");

    if (platformID > 35)
	sysLog("WARNING, Platform ID too large\n");

    if ((deploymentID < 0) || (deploymentID > 255))
    {
	sysLog("WARNING, Deployment ID out of range, setting to 0\n");
	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\n",
	   platformID, deploymentID);
}

