/* ****************************
 * *                          *
 * *      IRIS  System        *
 * * Product Printout Utility *
 * *                          *
 * ****************************
 * File: iris/examiners/productx.C
 * 
 *  COPYRIGHT (c) 1991, 1992, 1994, 1996, 1997, 1998, 1999, 2000,
 *                          2002, 2004  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. 
 */
#include <locale.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

#include "user_lib.h"
#include "config_lib.h"
#include "misc_lib.h"

#include "examiners.h"

struct command_line
{
  char sFile[PATHNAME_SIZE];
  UINT1 lNoExit;
  SINT4 iMaxLength;
};
/* Function prototypes used just within this file
 */
static void ProcessCommandLine
( struct command_line *pCommand_a,
  int iargc_a,
  char *sargv_a[] );

static void ShowCartesianData
( const struct cartesian_product *pProduct_a,
  SINT4 iLineLength_a );

static void product_wind
(const struct wind_product *pWind_a );

static void usage( void );

/* ====================================================================
 * This is a program to print out product data.
 */
int main( int iargc_a, char *sargv_a[] )
{
  MESSAGE istatus;
  const union generic_product *pProduct;
  SINT4 isize, ichannel;
  char  sPath[PATHNAME_SIZE];
  struct command_line Command;

  UINT2 lok;
  struct iris_setup         ISetup;
  const struct site_setup *pSSetup;

  /* -------------------------------------------------------------------- */

  setlocale( LC_ALL, "" );

  ProcessCommandLine( &Command, iargc_a, sargv_a );

  if( !Command.sFile[0] )
    {
      fprintf( stderr, "No input file specified\n" ) ;
      exit( EXIT_FAILURE ) ;
    }

  /* Load setup, don't abort if there is a problem. */
  istatus = irisload(NULL, &ISetup );
  if ( istatus != SS_NORMAL ) 
    {
      sig_signal( istatus );
      pSSetup = NULL;
    }
  else
    pSSetup = &ISetup.Site;

  /* Open the file */
  strcpy( sPath, Command.sFile );
  istatus = imapopen( sPath, 0, (void **)&pProduct, &isize, &ichannel );
  if ( istatus != SS_NORMAL )
    {
      /* If not found, try the RAW directory */
      set_product_dir( PROD_RAW, sPath ) ;
      strcat( sPath, Command.sFile );
      istatus = imapopen( sPath, 0, (void **)&pProduct, &isize, &ichannel );
      if ( istatus != SS_NORMAL )
	{
	  /* If not found, try the regular directory */
	  set_product_dir( PROD_PPI, sPath ) ;
	  strcat( sPath, Command.sFile );
	  istatus = imapopen( sPath, 0, (void **)&pProduct, &isize, &ichannel );
	  if ( istatus != SS_NORMAL )
	    {
	      sig_signal( istatus );
	      exit(EXIT_FAILURE);
	    }
	}
    }

  /* First do some checking based on the product header: */
  show_product( &pProduct->Header, pSSetup, isize, Command.sFile, &lok );
  if (!lok) exit(EXIT_FAILURE);

  switch( pProduct->Header.pcf.iptype )
    {
    case PROD_CATCH:
      product_catch( &pProduct->Catch, Command.iMaxLength );
      break;

    case PROD_FCAST:
      product_fcast( &pProduct->Header, Command.iMaxLength );
      break;

    case PROD_GAGE:
      product_gage( &pProduct->Header, Command.iMaxLength );
      break;

    case PROD_NDOP:
      product_ndop( &pProduct->Header, Command.iMaxLength ) ;
      break ;

    case PROD_RAW:
      product_raw( &pProduct->Raw ) ;
      break;

    case PROD_SLINE:
      product_sline( &pProduct->Sline, CENTROID_LABEL_AVERAGE ) ;
      break;

    case PROD_STATUS:
      product_status( &pProduct->Stat ) ;
      break;

    case PROD_TDWR:
      product_tdwr( &pProduct->Header ) ;
      break ;

    case PROD_TRACK:
      product_track( &pProduct->Track, CENTROID_LABEL_AVERAGE );
      break;

    case PROD_VVP:
      product_vvp(pProduct->Header.pcf.psi.vvp.ivvp_switch,
		  pProduct->Header.pcf.psi.vvp.ivvp_intervals, pProduct->Vvp.Results ) ;
      break;

    case PROD_WIND:
      product_wind( &pProduct->Wind ) ;
      break ;

    case PROD_WARN:
      product_warn( &pProduct->Warn, CENTROID_LABEL_AVERAGE ) ;
      break;

    case PROD_BEAM:
      ShowCartesianData( &pProduct->Cartesian, Command.iMaxLength );

    default:
      printf("PRODUCTX does not display data from this type of product.\n");
      break;
    }

  istatus = imapclose( pProduct, isize, ichannel );

  /* Exit, or just remain waiting here...
   */
  if( Command.lNoExit )
    for(;;) sig_microSleep( 250000 ) ;
  else
    exit( EXIT_SUCCESS ) ;
}

/* =======================================================
 * Process the command line.
 */
static void ProcessCommandLine
( struct command_line *pCommand_a,
  int iargc_a,
  char *sArgv_a[] )
{
  int iArg;

  /* Fill in default values */
  memset( pCommand_a, 0, sizeof(*pCommand_a) );
  pCommand_a->iMaxLength = 85;

  for( iArg=1 ; iArg<iargc_a ; iArg++ )
    {
      const char *sArg = sArgv_a[iArg];
      int ilen = strlen( sArg );
      if (sArg[0] == '-' )
        {
	  char *sEnd;
          if( ( 0 == strncasecmp( sArg, "-help", ilen ) ) ||
	      ( 0 == strncasecmp( sArg, "-?"   , ilen ) ) )
	    {
	      usage();
	  }
	  else if( 0 == strncasecmp( sArg, "-noexit", ilen ) )
	    {
	      pCommand_a->lNoExit = TRUE ;
	    }
	  else if ( 0 == strncasecmp( sArg, "-width:", 7 ))
	    {
	      pCommand_a->iMaxLength = strtol( &sArg[7], &sEnd, 10 );
	      if (&sArg[7]==sEnd) usage();
	      if (pCommand_a->iMaxLength<10)  pCommand_a->iMaxLength=10;
	      if (pCommand_a->iMaxLength>200) pCommand_a->iMaxLength=200;
	    }
	  else
	    {
	      usage();
	    }
        }
      else
	/* All commands without a leading "-" are assumed to be files. */
	{
	  if( pCommand_a->sFile[0] )
	    {
	      fprintf( stderr, "More than one input file specified\n" ) ;
	      exit( EXIT_FAILURE ) ;
	    }
	  else
	    {
	      strncpy( pCommand_a->sFile, sArg, PATHNAME_SIZE-1 );
	    }
	}
    }
}
/* ==============================================================
 * Print information about a horizontal wind field product.
 */
static void product_wind
  (const struct wind_product *pWind_a )
{
  SINT4 index, maxindex ;
  const struct vvp_results *pvvp = &pWind_a->Vvp;
  const struct wind_results *pwind = pWind_a->Results;

  /* First print information about the VVP that was run on the entire volume.
   */
  printf( "         ------------ VVP Results for Overall Volume ------------\n" ) ;
  product_vvp( pWind_a->Header.pcf.psi.wind.ivvp_switch, 1, pvvp ) ;

  /* Then loop through all of the wind_results structures.
   */
  printf( "\n      ---Counts--- Coverage   Range  Azimuth    Wind-Speed     Direction\n" ) ;

  maxindex = pWind_a->Header.pcf.psi.wind.irange_count *
             pWind_a->Header.pcf.psi.wind.iazimuth_count ;

  for( index = 0 ; index < maxindex ; index++, pwind++ ) {
    FLT4 fhvel, fhvel_std, fhdir, fhdir_std ;
    const FLT4 fxvel = 0.01 * (float)pwind->ixvel ;
    const FLT4 fxstd = 0.01 * (float)pwind->ixvel_std ;
    const FLT4 fyvel = 0.01 * (float)pwind->iyvel ;
    const FLT4 fystd = 0.01 * (float)pwind->iyvel_std ;

    printf( "%3d: %6d/%6d", index+1, pwind->idata_count, pwind->igeom_count ) ;

    if( pwind->igeom_count == 0 ) {
      printf( "   -----" ) ;
    } else {
      printf( " %6.1f%%",
	     100.0 * ((double)pwind->idata_count) / ((double)pwind->igeom_count) ) ;
    }

    printf( "   %6.1f  %6.1f",
	   ((double)pwind->icenter_range) / 1E5,
	   (double)fPDegFromBin2( pwind->icenter_az ) ) ;

    if( pwind->idata_count == 0 ) {
      printf( "     ----  ----    ----  ----\n" ) ;
    } else {
      fhvel     = sqrt( (fxvel * fxvel) + (fyvel * fyvel) ) ;
      fhvel_std = sqrt( (fxstd * fxstd) + (fystd * fystd) ) ;

      fhdir = 180.0 + (180.0 / FPI_P) * atan2( fxvel, fyvel ) ;
      if( fhdir > 360.0 ) fhdir -= 360.0 ;
      fhdir_std = 2.0 * (180.0 / FPI_P) * atan2( fhvel_std, fhvel ) ;

      printf( "    %5.1f,%5.1f   %5.1f,%5.1f\n",
	     (double)fhvel, (double)fhvel_std, (double)fhdir, (double)fhdir_std ) ;
    }
  }
}

/* ======================================================
 * Print cartesian array numbers on the terminal.  Handle
 * 1 byte data only for now.
 */
static void ShowCartesianData
( const struct cartesian_product *pProduct_a,
  SINT4 iLineLength_a )
  {
    SINT4 iX, iY, iPos, iSkipFactor;

    const struct product_configuration *pPcf=&(pProduct_a->Header.pcf);


    UINT4 iRes = idata_resolution( pPcf->idata_out );
    if (iRes!=8) return;
    SINT4 iMaxDisplay = (iLineLength_a-5)/4;
    if (iMaxDisplay<5) iMaxDisplay=5;
    iSkipFactor = (pPcf->ixsize+iMaxDisplay-1)/iMaxDisplay;
    
    printf( "Displaying cartesian data with skip factor %d\n", iSkipFactor );

    for (iY=pPcf->iysize-1; iY>=0; iY-=iSkipFactor)
      {
	printf("%4d:", iY );
	for (iX=0; iX<pPcf->ixsize; iX+=iSkipFactor)
	  {
	    iPos = iX + iY*pPcf->ixsize;
	    printf( "%4d", pProduct_a->Data[iPos] );
	  }
	printf( "\n" );
      }
  }

static void usage( void )
{
  fprintf( stderr, "productx options:\n");
  fprintf( stderr, "    -help       -- Print this list\n");
  fprintf( stderr, "    <file>      -- Specify the product file\n");
  fprintf( stderr, "    -noExit     -- Infinite loop when done\n");
  fprintf( stderr, "    -width:#    -- Specify maximum line length\n");
  exit(EXIT_FAILURE) ;
}
