/* ***********************************************************************
 * *                                                                     *
 * *  Class convert a Universal ASCII Lighting Format file to            *
 * *  an IRIS WARN product                                               *
 * *                                                                     *
 * ***********************************************************************
 * File: utils/ualf/UalfConvert.C
 *
 *                      COPYRIGHT (c) 2006  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 input file defining 
 * Universal ASCII Lighting Format (UALF) data and converts
 * it into an IRIS WARN product containing that data.
 *
 * Note if you are modifying this program, and wish to insert a diagnostic
 * printf, be sure to write it to the error output.
 */

#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>


#include "sigtypes.h"
#include "projection.h"
#include "setup.h"
#include "headers.h"
#include "product.h"
#include "signetwork.h"
#include "config_lib.h"
#include "misc_lib.h"
#include "himath_lib.h"
#include "user_lib.h"
#include "UalfConvert.h"
#include "UalfTokenize.h"

#define MAX_LINELENGTH (120)

/*******************************************************
**
** Private Methods
**
*******************************************************/
/* ===============================================================
 * 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>
 * SITENAME      <name>
 * VERBOSE
 *
 */
UINT2 UalfConvert::lProcessConfigLine
(char *sline_a,
 struct convert_config *pConfig_a )
{
  char *stokens[9], *sptr;
  UINT4 icount, ioffset;
  
  ioffset = 0;
  icount  = 0;
  /* Process up to 9 tokens, stop when the line is exhausted. */
  while (icount < 10) 
    {
      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( "ALLOW_ZERO_FOR_PEAK_CURNT", stokens[0] ) )
    {
      pConfig_a->lAllowZeroForPeakCurnt=TRUE;
      return FALSE;
    }

  /* See if the line contains the CENTER_LATLON command */
  if ( 0 == strcmp( "CENTER_LATLON", stokens[0] ) )
    {
      FLT8 fLatitude, fLongitude;
      if ( icount < 3 ) return TRUE;
      
      fLatitude = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      fLongitude = strtod( stokens[2], &sptr );
      if (sptr == stokens[2]) return TRUE;

      if (fLatitude  <  -90.0 ) return TRUE;
      if (fLatitude  >   90.0 ) return TRUE;
      if (fLongitude < -180.0 ) return TRUE;
      if (fLongitude >  180.0 ) return TRUE;

      pConfig_a->Projection.iCenterLat = iBin4FromFDeg(fLatitude);
      pConfig_a->Projection.iCenterLon = iBin4FromFDeg(fLongitude);
      return FALSE;
    }

  if ( 0 == strcmp( "DEBUG", stokens[0] ) )
    {
      pConfig_a->lDaemon=FALSE;
      return FALSE;
    }

  /* See if the line contains the ICON_POS_CURNT command */
  if ( 0 == strcmp( "ICON_POS_CURNT", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      strncpy( pConfig_a->sIconPosCurnt, stokens[1], 16 );
      return FALSE;
    }

  /* See if the line contains the ICON_NEG_CURNT command */
  if ( 0 == strcmp( "ICON_NEG_CURNT", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      strncpy( pConfig_a->sIconNegCurnt, stokens[1], 16 );
      return FALSE;
    }

  /* IRIS_DIRECTORY <directory> */
  if ( 0 == strcmp( "IRIS_DIRECTORY", stokens[0] ) )
    {
      int iLength;
      if ( icount < 2 ) return TRUE;

      strncpy( pConfig_a->sIrisDirectory, stokens[1], DIRECTORY_SIZE-1 );
      /* Make sure directory has a trailing / */
      iLength = strlen( pConfig_a->sIrisDirectory );
      if (pConfig_a->sIrisDirectory[iLength-1] != '/' )
        {
          if (iLength<(DIRECTORY_SIZE-1))
            pConfig_a->sIrisDirectory[iLength] = '/';
          else
            return TRUE;
        }

      return FALSE;
    }

  /* IRIS_HOST <host_name> */
  if ( 0 == strcmp( "IRIS_HOST", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;

      strncpy( pConfig_a->sIrisHost, stokens[1], 39 );

      return FALSE;
    }

  /* IRIS_PORT <port_number> */
  if ( 0 == strcmp( "IRIS_PORT", stokens[0] ) )
    {
      char *sptr;

      if ( icount < 2 ) return TRUE;

      pConfig_a->iIrisPort = strtol( stokens[1], &sptr, 10 );
      if (sptr == stokens[1]) return TRUE;
      if (pConfig_a->iIrisPort < MIN_USER_PORT) return TRUE;

      return FALSE;
    }


  /* See if the line contains the LAT_MIN_MAX command */
  if ( 0 == strcmp( "LAT_MIN_MAX", stokens[0] ) )
    {
      FLT8 fLatMin, fLatMax;
      if ( icount < 3 ) return TRUE;
      
      fLatMin = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      fLatMax = strtod( stokens[2], &sptr );
      if (sptr == stokens[2]) return TRUE;

      if (fLatMin  <  -90.0 ) return TRUE;

      if (fLatMax  <  -90.0 ) return TRUE;
      if (fLatMax  >   90.0 ) return TRUE;

      pConfig_a->fLatMin = fLatMin;
      pConfig_a->fLatMax = fLatMax;
      return FALSE;
    }

  /* See if the line contains the LON_MIN_MAX command */
  if ( 0 == strcmp( "LON_MIN_MAX", stokens[0] ) )
    {
      FLT8 fLonMin, fLonMax;
      if ( icount < 3 ) return TRUE;
      
      fLonMin = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      fLonMax = strtod( stokens[2], &sptr );
      if (sptr == stokens[2]) return TRUE;

      if (fLonMin < -180.0 ) return TRUE;
      if (fLonMin >  180.0 ) return TRUE;
      if (fLonMax < -180.0 ) return TRUE;
      if (fLonMax >  180.0 ) return TRUE;

      pConfig_a->fLonMin = fLonMin;
      pConfig_a->fLonMax = fLonMax;
      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;
    }

  /* See if the line contains the MAX_RANGE command */
  if ( 0 == strcmp( "MAX_RANGE", stokens[0] ) )
    {
      FLT8 fRMax;
      if ( icount < 2 ) return TRUE;
      
      fRMax = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      if (fRMax <    1.0 ) return TRUE;
      if (fRMax > 3000.0 ) return TRUE;

      pConfig_a->Projection.fRMax = fRMax;
      return FALSE;
    }

  /* NEW_PRODUCT_TIME_INTERVAL <seconds> */
  if ( 0 == strcmp( "NEW_PRODUCT_TIME_INTERVAL", stokens[0] ) )
    {
      char *sptr;

      if ( icount < 2 ) return TRUE;

      pConfig_a->iNewProductTimeInterval = strtol( stokens[1], &sptr, 10 );
      if (sptr == stokens[1]) return TRUE;
      pConfig_a->iNewProductTimeInterval = 
        (pConfig_a->iNewProductTimeInterval / 5) * 5;
      if ((pConfig_a->iNewProductTimeInterval < 5) ||
          (pConfig_a->iNewProductTimeInterval > 120))
        return TRUE;

      return FALSE;
    }

  /* See if the line contains the PRODUCTNAME command */
  if ( 0 == strcmp( "PRODUCTNAME", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      nullify_ncpy( pConfig_a->sProductName, stokens[1], 12 );
      return FALSE;
    }


  /* See if the line contains the PROJECTION file command */
  if ( 0 == strcmp( "PROJECTION", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      pConfig_a->Projection.iType = iProjectionFromName16( stokens[1] );
      if (pConfig_a->Projection.iType >= MAPROJ_COUNT ) return TRUE;
      return FALSE;      
    }

  /* See if the line contains the RADAR_LATLON command */
  if ( 0 == strcmp( "RADAR_LATLON", stokens[0] ) )
    {
      FLT8 fLatitude, fLongitude;
      if ( icount < 3 ) return TRUE;
      
      fLatitude = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      fLongitude = strtod( stokens[2], &sptr );
      if (sptr == stokens[2]) return TRUE;

      if (fLatitude  <  -90.0 ) return TRUE;
      if (fLatitude  >   90.0 ) return TRUE;
      if (fLongitude < -180.0 ) return TRUE;
      if (fLongitude >  180.0 ) return TRUE;

      pConfig_a->Projection.iRadarLat = iBin4FromFDeg(fLatitude);
      pConfig_a->Projection.iRadarLon = iBin4FromFDeg(fLongitude);
      return FALSE;
    }

  /* See if the line contains the SITENAME command */
  if ( 0 == strcmp( "SITENAME", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      spacify_ncpy( pConfig_a->sIngSitename, stokens[1], 16 );
      return FALSE;
    }

  /* TIME_DIFF <seconds> */
  if ( 0 == strcmp( "TIME_DIFF", stokens[0] ) )
    {
      char *sptr;

      if ( icount < 2 ) return TRUE;

      pConfig_a->iInitialTimeOffset = strtol( stokens[1], &sptr, 10 );
      if (sptr == stokens[1]) return TRUE;

      return FALSE;
    }

  /* UALF_HOST <host_name> */
  if ( 0 == strcmp( "UALF_HOST", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;

      strncpy( pConfig_a->sUalfHost, stokens[1], 39 );

      return FALSE;
    }


  /* UALF_PORT <port_number> */
  if ( 0 == strcmp( "UALF_PORT", stokens[0] ) )
    {
      char *sptr;

      if ( icount < 2 ) return TRUE;

      pConfig_a->iUalfPort = strtol( stokens[1], &sptr, 10 );
      if (sptr == stokens[1]) return TRUE;
      if (pConfig_a->iUalfPort < MIN_USER_PORT) return TRUE;

      return FALSE;
    }

  /* See if the line contains the SITENAME command */
  if ( 0 == strcmp( "WARNING_REGION_NAME", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      spacify_ncpy( pConfig_a->sWarnRegionName, stokens[1], 12 );
      pConfig_a->sWarnRegionName[11] = 0;
    
      return FALSE;
    }
  
  if ( 0 == strcmp( "VERBOSE", stokens[0] ) )
    {
      pConfig_a->lVerbose = TRUE;
      return FALSE;
    }

  if ( 0 == strcmp( "X_SIZE", stokens[0] ) )
    {
      SINT4 iXSize;
      if ( icount < 2 ) return TRUE;
      iXSize = strtol( stokens[1], &sptr, 10 );
      /* Invalid parse is detected here */
      if (iXSize<MIN_PRODUCT_SIZE) return TRUE;
      if (iXSize>MAX_PRODUCT_SIZE) return TRUE;
      pConfig_a->Projection.iXSize = iXSize;
      return FALSE;
    }
  
  /* Unrecognized lines will generate a syntax error */
  return TRUE;
}

/* ===============================================
 * Fill in the radar position in pixels*1000, etc., from other information
 * in the setup file.
 */
void UalfConvert::fillProjectionNumbers
( struct projection_summary *pProj_a )
{ 
  MESSAGE istatus;
  struct mpj_projection8 mpj;
  struct mpj_region8     region;

  /* As a default, set reference to center */
  pProj_a->iReferenceLat = pProj_a->iCenterLat;
  pProj_a->iReferenceLon = pProj_a->iCenterLon;

  /* Initialize outputs in case of an error return
   */
  pProj_a->iXRadPos = 0;
  pProj_a->iYRadPos = 0;
  pProj_a->iYSize  = pProj_a->iXSize;
  pProj_a->iXScale = 100000;
  pProj_a->iYScale = 100000;

  mpj.iprojection_type = pProj_a->iType;
  mpj.Ref.fLat         = fRadianFromBin4( pProj_a->iReferenceLat );
  mpj.Ref.fLon         = fRadianFromBin4( pProj_a->iReferenceLon );

  region.Loc1.fLat = fRadianFromBin4( pProj_a->iCenterLat );
  region.Loc1.fLon = fRadianFromBin4( pProj_a->iCenterLon );
  region.fde  = pProj_a->fRMax;
  region.fdn  = pProj_a->fRMax;
  region.fxpix = (FLT8)pProj_a->iXSize;
  istatus = mpj_pin_region( &mpj, &region, MPJ_LOC1|MPJ_FDE|MPJ_FDN );
  if (istatus != SS_NORMAL)
  {
    sig_signal( istatus );
    return;
  }

  /* Fill in the final X & Y sizes and scales
   */
  pProj_a->iXSize  = NINT( region.fxpix );
  pProj_a->iYSize  = NINT( region.fypix );
  pProj_a->iXScale = NINT( 200000.0*region.fde/region.fxpix);
  pProj_a->iYScale = NINT( 200000.0*region.fdn/region.fypix);
  
  /* Fill in the radar location in fractional pixels within the
   * data array.  If pointer is NULL, then use the center.
   */
  struct latlon8 RadarEarth;
  struct XYPoint8 Pix; UINT1 lValid;
  RadarEarth.fLat = fRadianFromBin4( pProj_a->iRadarLat ) ;
  RadarEarth.fLon = fRadianFromBin4( pProj_a->iRadarLon ) ;
    
  mpj_earth_to_pixel( &mpj, &region, &RadarEarth, &Pix, &lValid ) ;
    
  pProj_a->iXRadPos = NINT( 1000.0 * Pix.fX ) ;
  pProj_a->iYRadPos = NINT( 1000.0 * Pix.fY ) ;
  return;
}

/* ===============================================
 * Process on line of the input data.
 */
UINT1 UalfConvert::lProcessAsciiLine
( char *sline_a,
  struct warn_product *pWarnProduct_a,   /* Pointer will be updated */
  UINT1 lfirstpass_a)
{
  UalfTokenize ualf_tok;
  static UINT2  lhas_header;
  static struct ymds_time hdr_time;
//  static SINT4 iold_min = -1;
//  static SINT4 iold_sec = -1;

  if (lfirstpass_a)
  {
    pWarnProduct_a->Header.end.iresults_count = 0;
    lhas_header = false;
  }

  if (ualf_tok.tokenize(sline_a))
  {
    //Check if a header line
    if (ualf_tok.getVersion() == 9)
    {
      if (ualf_tok.getTokCnt() == ualf_tok.getMaxHdrParams())
      {
        lhas_header = true;
        memset(&hdr_time, 0, sizeof(hdr_time));
        hdr_time = ualf_tok.getYmdsTime(); 
        pWarnProduct_a->Header.pcf.ing_time = hdr_time;
        pWarnProduct_a->Header.pcf.epoch = hdr_time;
        return FALSE;
      }
      else
      {
        Lprintf("Bad header parameters\n");
        return  TRUE;
      }
    }
    else
    { 
      FLT8 flat = ualf_tok.getLat();
      FLT8 flon = ualf_tok.getLon();
      FLT8 flat_min = getLatMin();
      FLT8 flat_max = getLatMax();
      FLT8 flon_min = getLonMin();
      FLT8 flon_max = getLonMax();

      //Filter out all UALF data that has a Lat/Lot of 0.0
      if ((flat == 0.0) && (flon == 0.0))
        return  TRUE;

      //Filter out all UALF data that is not within
      //Min Max range

      if (((flat < flat_min) || (flat > flat_max)) ||
          ((flon < flon_min) || (flon > flon_max)))
      {
        return  TRUE;
      }

      //Filter out all UALF data that has a peak current of 0
      //but only if not allowed
      if ((ualf_tok.getPeakCurnt() == 0))
      {
        if (!CSetup.lAllowZeroForPeakCurnt)
          return  TRUE;
      }
    }
  }
  else
  {
    Lprintf("++++TOKEONEIZEING PROBLEM\n");
    return  TRUE;
  }

  //Check token count 
  if (ualf_tok.getTokCnt() < ualf_tok.getMaxParams())
  {
    Lprintf("Not enough parameters\n");
    return  TRUE;
  }
  else if (ualf_tok.getTokCnt() > ualf_tok.getMaxParams())
  {
    Lprintf( "To many parameters\n");
    return  TRUE;
  }

  //Next Check All Params
  if (ualf_tok.getVersion() != 0 ) 
    return TRUE;

  if ((ualf_tok.getPeakCurnt() < -9999)||(ualf_tok.getPeakCurnt() > 9999)) return TRUE;
  if ((ualf_tok.getLat() < -90.0)||(ualf_tok.getLat() > 90.0)) return TRUE;
  if ((ualf_tok.getLon() < -180.0)||(ualf_tok.getLon() > 180.0)) return TRUE;
  if ((ualf_tok.getEllipseAng() < 0)||(ualf_tok.getEllipseAng() > 180.0)) return TRUE;

/*
  //Check if the current lighting stroke happened
  //in the same second as the last on.  If so then skip. 
  if ((iold_min == imin) && (iold_sec == isec))
    return FALSE;

  iold_min = imin;
  iold_sec = isec;
*/

  if(lhas_header)
  { 
    pWarnProduct_a->Header.pcf.ing_time = hdr_time;
    pWarnProduct_a->Header.pcf.epoch = hdr_time;
  }
  else
  {
    pWarnProduct_a->Header.pcf.ing_time = ualf_tok.getYmdsTime(); 
    pWarnProduct_a->Header.pcf.epoch = ualf_tok.getYmdsTime(); 
  }

  int icnt = pWarnProduct_a->Header.end.iresults_count;
  pWarnProduct_a->Results[icnt].ilatitude = iBin4FromFDeg( ualf_tok.getLat() );
  pWarnProduct_a->Results[icnt].ilongitude = iBin4FromFDeg( ualf_tok.getLon() );

  pWarnProduct_a->Results[icnt].iaverage_value[0] = abs(ualf_tok.getPeakCurnt()) * 100; 
  pWarnProduct_a->Results[icnt].iaverage_value[1] = abs(ualf_tok.getPeakCurnt()) * 100; 
  pWarnProduct_a->Results[icnt].iaverage_value[2] = abs(ualf_tok.getPeakCurnt()) * 100; 
  pWarnProduct_a->Results[icnt].imax_value[0] = abs(ualf_tok.getPeakCurnt()) * 100; 
  pWarnProduct_a->Results[icnt].imax_value[1] = abs(ualf_tok.getPeakCurnt()) * 100; 
  pWarnProduct_a->Results[icnt].imax_value[2] = abs(ualf_tok.getPeakCurnt()) * 100; 

  pWarnProduct_a->Results[icnt].iprotect_mask = 
      pWarnProduct_a->Header.pcf.psi.warn.iprotect_mask;

  //Used Plus or Minus Symbol here
  if (ualf_tok.getPeakCurnt() >= 0)
    strcpy(pWarnProduct_a->Results[icnt].stext, CSetup.sIconPosCurnt);
  else
    strcpy(pWarnProduct_a->Results[icnt].stext, CSetup.sIconNegCurnt);

  pWarnProduct_a->Results[icnt].iEllipseAngle = iBin4FromFDeg(ualf_tok.getEllipseAng());
  pWarnProduct_a->Results[icnt].iEllipseMajor = ualf_tok.getEllipseMajor();
  pWarnProduct_a->Results[icnt].iEllipseMinor = ualf_tok.getEllipseMinor();

  int ihgt = 10;
  pWarnProduct_a->Results[icnt].iheight = ihgt * 10000;
  pWarnProduct_a->Header.end.iresults_count++;

  return FALSE;
}


/*******************************************************
**
** Public Methods
**
*******************************************************/
/* ======================================================================
 * Function to process the command line arguments.
 */
void UalfConvert::processCommandLine
(int iArgc_a, 
 char *sArgv_a[] )
{
  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 (0 == strncmp( sArg, "-h", 2 ))
      Usage();
  }
  return;
}

/* ============================================================
 * Function to load the convert setup from a configuration file.
 */
void UalfConvert::loadSetup( )
{
  char sPath[PATHNAME_SIZE];
  char sline[81], *sptr;
  FILE* stream;
  SINT4 iline;
  UINT2 lerror;
  int   ierror;

  /* Initialize the data to the default values */
  memset( &CSetup, 0, sizeof(CSetup) );
  spacify_ncpy( CSetup.sIngSitename, "UNKNOWN", 16 );
  nullify_ncpy( CSetup.sProductName, "UALF", 12 );
  /* Default location is 0 0 latlon, AED, max range=100 km */
  CSetup.Projection.fRMax = 100.0;
  CSetup.Projection.iType = MAPROJ_AZIMUTHAL;
  CSetup.Projection.iXSize = 480;
  CSetup.lAllowZeroForPeakCurnt = FALSE;
  CSetup.iUalfPort = 12345;
  CSetup.iNewProductTimeInterval = 15;
  CSetup.fLatMin = -90.0;
  CSetup.fLatMax = 90.0;
  CSetup.fLonMin = -180.0;
  CSetup.fLonMax = 180.0;
  CSetup.iInitialTimeOffset = 0;
  strcpy(CSetup.sIconPosCurnt, "plus");
  strcpy(CSetup.sIconNegCurnt, "minus");
  strcpy( CSetup.sUalfHost, "127.0.0.1" );
  CSetup.iIrisPort    = PORT_INPUT_RECEIVER;
  ierror = gethostname( CSetup.sIrisHost, 39 );
  if (ierror==-1) sig_signal( errno_to_message(errno) );
  strcpy( CSetup.sIrisDirectory, "/usr/iris_data/UalfRelayIn/" );
  CSetup.lDaemon = TRUE;
  
  /* 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, "UalfToIris.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 = lProcessConfigLine( sptr, &CSetup );
    if (lerror)
      fprintf(stderr, "Syntax error on config file line %d\n", iline );
    iline +=1;
    sptr = fgets( sline, 81, stream );
  }

  fclose( stream );

  fillProjectionNumbers( &CSetup.Projection );

  return;
}

void UalfConvert::setupLogging( )
{
  /* Open the logging file, if any */
  if (CSetup.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, "UalfToIris.log" );
    CSetup.iLogFile = fopen( sLogPath, "w" );
    if (NULL == CSetup.iLogFile)
    {
      fprintf(stderr, "Can not open log file: '%s'\n", sLogPath );
      exit(EXIT_FAILURE);
    }
  }

  /* Do some cross checking */
  if (CSetup.lDaemon && CSetup.lLogToTerm)
  {
    fprintf( stderr, "Warning: Cannot log to terminal without DEBUG option\n" ) ;
    CSetup.lLogToTerm=FALSE;
  }

  /* Starting here we can use the Lprintf function */
  if (CSetup.lVerbose)
    Lprintf( "Verbose Logging On.\n");

}

/* ===============================================
 * Fill in the product header.
 */
void UalfConvert::initializeProdHeader(struct warn_product *pWarnProduct_a)
{
  int ii;

  HeaderFromScratch( &pWarnProduct_a->Header, NULL, CSetup.sIngSitename,
		     CSetup.sIngSitename, CSetup.sProductName );
  pWarnProduct_a->Header.pcf.iptype    = PROD_WARN;

  pWarnProduct_a->Header.pcf.ixscale   = CSetup.Projection.iXScale;
  pWarnProduct_a->Header.pcf.iyscale   = CSetup.Projection.iYScale;
  pWarnProduct_a->Header.pcf.izscale   = 0;
  pWarnProduct_a->Header.pcf.ixsize    = CSetup.Projection.iXSize;
  pWarnProduct_a->Header.pcf.iysize    = CSetup.Projection.iYSize;
  pWarnProduct_a->Header.pcf.izsize    = 1;
  pWarnProduct_a->Header.pcf.ixrad     = CSetup.Projection.iXRadPos;
  pWarnProduct_a->Header.pcf.iyrad     = CSetup.Projection.iYRadPos;
  pWarnProduct_a->Header.pcf.izrad     = 0;

  pWarnProduct_a->Header.pcf.idata_out = DB_NULL;
  
  for (ii = 0; ii <= WARN_MAX_INPUTS; ii++)
     pWarnProduct_a->Header.pcf.psi.warn.iwarn_prods[ii] = PROD_WARN;

  pWarnProduct_a->Header.pcf.iprojection_type = CSetup.Projection.iType;

  pWarnProduct_a->Header.end.ilat_center = CSetup.Projection.iCenterLat;
  pWarnProduct_a->Header.end.ilon_center = CSetup.Projection.iCenterLon;

  pWarnProduct_a->Header.end.ilat_ref = CSetup.Projection.iReferenceLat;
  pWarnProduct_a->Header.end.ilon_ref = CSetup.Projection.iReferenceLon;

  //Add Say/Beep Warning
  pWarnProduct_a->Header.pcf.iflags |= PF_WARN_SAY;

  ////////////////////////////////////////////
  //Load Iris Setup
  ////////////////////////////////////////////
  MESSAGE     istatus;
  struct      iris_setup  irisSetup;
  memset( &irisSetup, 0, sizeof(struct iris_setup));

  istatus = irisload(NULL, &irisSetup);
  if( istatus != SS_NORMAL )
  {
    fprintf( stderr, "Could not load iris_seutps\n");
    exit(EXIT_FAILURE);
  }

  //Copy setups protected_regions to warn product.
  pWarnProduct_a->Header.pcf.psi.warn.iprotect_mask = 0;
  for (ii = 0; ii < IMAX_PROT_REGIONS; ii++)
  {
    irisSetup.protect.protected_regions[ii].sname[11]= 0;
    pWarnProduct_a->Protect.protected_regions[ii]  = irisSetup.protect.protected_regions[ii];
    if (!strcmp(getWarnRegionName(), pWarnProduct_a->Protect.protected_regions[ii].sname))
    {
      pWarnProduct_a->Header.pcf.psi.warn.iprotect_mask =
        IBSET(pWarnProduct_a->Header.pcf.psi.warn.iprotect_mask, ii);
    }
  }

  //Check if any warn regions were set.
  if (pWarnProduct_a->Header.pcf.psi.warn.iprotect_mask == 0)
    fprintf(stderr,"No Warn Regions Found\n");

//  warnProduct.Header.pcf.psi.warn.iwarn_area = 1000000;
//  strcpy(warnProduct.Header.pcf.psi.warn.swarn_symbol,    "DOUG_SWARN_SYMBOL");
//  strcpy(warnProduct.Header.pcf.psi.warn.swarn_names,    "ED1");

}

/* ==================================================
 */
void UalfConvert::Usage( void )
{
  fprintf( stderr, "Options: -help\n" );
  fprintf( stderr, "         (all other arguments ignored)\n" );
  exit(EXIT_FAILURE) ;
}

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

  struct full_time_spec Time;
  char sTimeBuf[TIMENAME_SIZE];
  GetTimeFull( &Time, TIME_FLG_LOCAL );

  if (CSetup.lLogToTerm)
  {
    shhmmssddmonyyyy_r( &Time.Ymds, sTimeBuf );
    fprintf( stderr, "%s %s:", sTimeBuf, Time.sRecordTZName );
    fputs( sString_a, stderr );
  }

  if (CSetup.lLogToFile)
  {
    shhmmssddmonyyyy_r( &Time.Ymds, sTimeBuf );
    fprintf( CSetup.iLogFile, "%s %s:", sTimeBuf, Time.sRecordTZName );
    fputs( sString_a, CSetup.iLogFile );
    fflush( CSetup.iLogFile );
  }
}

char *UalfConvert::getWarnRegionName()
{
  return CSetup.sWarnRegionName;
}

char *UalfConvert::getIrisDirectory()
{
  return CSetup.sIrisDirectory;
}

char *UalfConvert::getIrisHost()
{
  return CSetup.sIrisHost;
}

UINT4 UalfConvert::getIrisPort()
{
  return CSetup.iIrisPort;
}

char *UalfConvert::getUalfHost()
{
  return CSetup.sUalfHost;
}

UINT4 UalfConvert::getUalfPort()
{
  return CSetup.iUalfPort;
}

UINT1 UalfConvert::isVerbose()
{
  return CSetup.lVerbose;
}

UINT1 UalfConvert::isDaemon()
{
  return CSetup.lDaemon;
}

UINT4 UalfConvert::getNewProdTimeInterval()
{
  return CSetup.iNewProductTimeInterval;
}

FLT8 UalfConvert::getLatMin()
{
  return CSetup.fLatMin;
}

FLT8 UalfConvert::getLatMax()
{
  return CSetup.fLatMax;
}

FLT8 UalfConvert::getLonMin()
{
  return CSetup.fLonMin;
}

FLT8 UalfConvert::getLonMax()
{
  return CSetup.fLonMax;
}

SINT4 UalfConvert::getInitialTimeOffset()
{
  return CSetup.iInitialTimeOffset;
}


