/* *************************************************************
 * *                                                           *
 * *  Function to change the task name of an IRIS RAW product  *
 * *                                                           *
 * *************************************************************
 * File: utils/pipes_in/ChangeTaskName.C
 *
 *                      COPYRIGHT (c) 2000, 2003  BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */

/* This program is a pipe which takes an IRIS RAW product in the standard input
 * and writes a modified product out the standard output.  It will not work
 * on byte swapped products, probably.
 *
 * Note if you are modifying this program, and wish to insert a diagnostic
 * printf, be sure to write it to the error output.
 */

#include <locale.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sigtypes.h"
#include "dsp.h"
#include "headers.h"
#include "iris_task.h"
#include "ingest.h"
#include "product.h"
#include "user_lib.h"

/* This holds information to customize the convertor */
#define TASK_CHANGE_MAX (5)
struct task_table
{
  char sOldTask[12];  /* Both space padded */
  char sNewTask[12];
};
struct convert_config
{
  UINT1 lLogToFile;
  UINT1 lLogToTerm;
  UINT1 lVerbose;             /* Log more details */
  UINT1 lAppendToLog;         /* Do not erase file each time */
  FILE *iLogFile;             /* Open file descriptor to log file */
  SINT4 iTaskCount;
  struct task_table Tasks[TASK_CHANGE_MAX];
};

struct convert_config CConfig_c;

/* Local function prototypes
 */
static void ChangeProductHeader
(struct product_hdr *phdr_a );

static void ChangeIngestHeader
(struct ingest_header *pIHdr_a );

static void ProcessCommandLine
(int iArgc, 
 char *sArgv[],
 char sFilename_a[FILENAME_SIZE] );

static void Usage( void );

static void LoadSetup
( struct convert_config *pCSetup_a );

static UINT2 ProcessConfigLine
(char *sline_a,
 struct convert_config *pCSetup_a );

static void Lprintf
( const char *sString_a );

/* ===============================================================
 * Main program starts here.
 */
int main(int iArgc, char *sArgv[])
{
  char sFileName[FILENAME_SIZE];
  SINT4 iSize, iReadCount;
  UINT1 iBuffer[TAPE_RECORD_LEN];
  char log_str[200];

  setlocale( LC_ALL, "" ) ;

  /* Process the command line arguments */
  ProcessCommandLine( iArgc, sArgv, sFileName );

  /* Process the setup file, if any */
  LoadSetup( &CConfig_c );

  /* Open the logging file, if any */
  if (CConfig_c.lLogToFile)
    {
      char *sptr;
      char sLogPath[PATHNAME_SIZE];
      sptr = getenv( "IRIS_LOG" );
      if (sptr)
	{
	  strncpy( sLogPath, sptr, PATHNAME_SIZE-20 );
	  sLogPath[PATHNAME_SIZE-20] = 0;
	}
      else
	strcpy( sLogPath, "/tmp/" );
      strcat( sLogPath, "ChangeTaskName.log" );
      if (CConfig_c.lAppendToLog)
	CConfig_c.iLogFile = fopen( sLogPath, "a" );
      else
	CConfig_c.iLogFile = fopen( sLogPath, "w" );
      if (NULL == CConfig_c.iLogFile)
	{
	  fprintf( stderr, "Can not open log file: '%s'\n", sLogPath );
	  exit(EXIT_FAILURE);
	}
    }

  /* Starting here we can use the Lprintf function */
  
  sprintf(log_str, "Processing input file: %s\n", sFileName );
  Lprintf(log_str);

  /****
       The file is an array of TAPE_RECORD_LEN records.
  ****/
  
  iReadCount = 0;
  iSize = fread(iBuffer, sizeof(char), TAPE_RECORD_LEN, stdin); 
  while( iSize == TAPE_RECORD_LEN )
    {
      iReadCount++;
      switch( iReadCount )
	{
	case 1:
	  ChangeProductHeader( (struct product_hdr *)iBuffer );
	  break;
	case 2:
	  ChangeIngestHeader( (struct ingest_header *)iBuffer );
	  break;

	}
      fwrite(iBuffer, 1, TAPE_RECORD_LEN, stdout);  
      iSize = fread(iBuffer, sizeof(char), TAPE_RECORD_LEN, stdin); 
    }

  exit( EXIT_SUCCESS );
}
/* ======================================
 * Change task name in the product header
 */
static void ChangeProductHeader
(struct product_hdr *phdr_a )
{
  SINT4 ii;
  for (ii=0; ii<CConfig_c.iTaskCount; ii++)
    {
      if (memcmp( phdr_a->pcf.stname, CConfig_c.Tasks[ii].sOldTask, 12 ))
	memcpy( phdr_a->pcf.stname, CConfig_c.Tasks[ii].sNewTask, 12 );
    }
}
/* ======================================
 * Change task name in the ingest header
 */
static void ChangeIngestHeader
(struct ingest_header *pIHdr_a )
{
  SINT4 ii;
  for (ii=0; ii<CConfig_c.iTaskCount; ii++)
    {
      if (memcmp( pIHdr_a->tcf.end.stname, CConfig_c.Tasks[ii].sOldTask, 12 ))
	memcpy( pIHdr_a->tcf.end.stname, CConfig_c.Tasks[ii].sNewTask, 12 );
    }
}

/* ======================================================================
 * Function to process the command line arguments.
 */
static void ProcessCommandLine
(int iArgc_a, 
 char *sArgv_a[],
 char sFilename_a[FILENAME_SIZE] )
{

  int iArg;

  /* Parse command line options
   */
  for( iArg=1 ; iArg<iArgc_a ; iArg++ )
    {
      const char *sArg = sArgv_a[iArg];
      /* fprintf( stderr, "Processing %d: '%s'\n", iArg, sArg ); */

      if (sArg[0] == '-')
	{
	  if (0 == strncmp( sArg, "-h", 2 ))
	    {
	      Usage();
	    }
	}
      else
	strncpy( sFilename_a, sArg, FILENAME_SIZE-1 );
      
    }
  return;
}
/* ==================================================
 */
static void Usage( void )
{
  fprintf( stderr, "Options: -help\n" );
  fprintf( stderr, "         filename\n" );
  fprintf( stderr, "         (all other arguments ignored)\n" );
  exit(EXIT_FAILURE) ;
}

/* ============================================================
 * Function to load the convert setup from a configuration file.
 */
static void LoadSetup
( struct convert_config *pCSetup_a )
{
  char sPath[PATHNAME_SIZE];
  char sline[81], *sptr;
  FILE* stream;
  SINT4 iline;
  UINT2 lerror;

  /* Initialize the data to the default values */
  memset( pCSetup_a, 0, sizeof(*pCSetup_a) );

  /* Generate the file name and open the file */
  sptr = getenv( "IRIS_CONFIG" );
  if (NULL == sptr) 
    {
      sig_signal_va( USER_NO_ENV, 1, "IRIS_CONFIG" );
      exit(EXIT_FAILURE);
    }

  strncpy( sPath, sptr, 140 );
  strcat( sPath, "ChangeTaskName.conf" );
  stream = fopen( sPath, "r" );

  /* Don't worry about a missing config file */
  if (NULL == stream) return;

  /* now loop through the file reading and parsing lines */
  iline = 1;
  sptr = fgets( sline, 81, stream );
  while (NULL != sptr)
    {
      lerror = ProcessConfigLine( sptr, pCSetup_a );
      if (lerror) fprintf( stderr, "Syntax error on ChangeTaskName.conf file line %d\n", iline );
      iline +=1;
      sptr = fgets( sline, 81, stream );
    }

  fclose( stream );

  return;
}

/* ===============================================================
 * Process one line from the configuration file.  Returns nonzero if there
 * is a syntax error.
 *
 * The config can contain the following commands.  All blank lines and
 * lines beginning with "#" are ignored.  Commands can be in any order.
 * Commands take effect in the order received.  For example, syntax errors
 * before the LOG command will not be logged.
 *
 * LOG           <FILE TERM BOTH NONE>
 * SITE name16 name3 lat long
 * VERBOSE
 *
 *
 */
static UINT2 ProcessConfigLine
(char *sline_a,
 struct convert_config *pConfig_a )
{
  char *stokens[9];
  UINT4 icount, ioffset;
  
  ioffset = 0;
  icount  = 0;
  /* Process up to 9 tokens, stop when the line is exhausted. */
  while (icount<9) 
    {
      stokens[icount] = sigtok( sline_a, &ioffset );
      if (NULL == stokens[icount])
	break;
      else
	icount++;
    }
  
  /* Blank lines are allowed and skipped */
  if (icount == 0) return FALSE;
  
  /* Skip commented lines */
  if (stokens[0][0] == '#') return FALSE;
  
  if ( 0 == strcmp( "APPEND_TO_LOG", stokens[0] ) )
    {
      pConfig_a->lAppendToLog=TRUE;
      return FALSE;
    }
  
  /* See if the line contains the LOG file command */
  if ( 0 == strcmp( "LOG", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      if      ( 0 == strcmp( "BOTH", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "FILE", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=FALSE;}
      else if ( 0 == strcmp( "TERM", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "NONE", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=FALSE;}
      else
	return TRUE;
      return FALSE;
    }

  if ( 0 == strcmp( "TASK", stokens[0] ) )
    {
      struct task_table *pTask;
      if (icount<3) return TRUE;
      if (pConfig_a->iTaskCount>=TASK_CHANGE_MAX) return TRUE;

      pTask = &pConfig_a->Tasks[pConfig_a->iTaskCount];
      spacify_ncpy( pTask->sOldTask, stokens[1], 12 );
      spacify_ncpy( pTask->sNewTask, stokens[2], 12 );
      pConfig_a->iTaskCount++;
      return FALSE;
    }
  
  if ( 0 == strcmp( "VERBOSE", stokens[0] ) )
    {
      pConfig_a->lVerbose = TRUE;
      return FALSE;
    }

  /* Unrecognized lines will generate a syntax error */
  return TRUE;
}

/* ===========================================
 * Print string to log and terminal, if desired.
 */
static void Lprintf
( const char *sString_a )
{
  if (CConfig_c.lLogToTerm) fputs( sString_a, stderr );
  if (CConfig_c.lLogToFile)
    {
      fputs( sString_a, CConfig_c.iLogFile );
      fflush( CConfig_c.iLogFile );
    }
}
