/* **********************************************************************
 * *                                                                    *
 * *   Header for all SIGMET HDF5 code                                  *
 * *                                                                    *
 * **********************************************************************
 * File: utils/HDF5/SigH5Func.h
 *
 *                     COPYRIGHT (c) 2003, 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.
 */


#ifndef SIGH5FUNC_H
#define SIGH5FUNC_H

#ifdef SIGH5FUNC_ALLOCATE
#define EXTERN
#else
#define EXTERN extern
#endif

#define OBJECT_TYPE_UNKNOWN  0
#define OBJECT_TYPE_IMAGE    1
#define OBJECT_TYPE_COMP     2
#define OBJECT_TYPE_VP       3
#define OBJECT_TYPE_XSEC     4
#define OBJECT_TYPE_PVOL     5
#define OBJECT_TYPE_SCAN     6

#define DATATYPE_UNKNOWN      0 
#define DATATYPE_UCHAR        1 
#define DATATYPE_USHORT       2 
#define DATATYPE_INT          3 
#define DATATYPE_FLOAT        4 

#define N2_MAX_NODE_SIZE (4)

class SigH5Func 
{
 private:
  int getDataType(hid_t hdata_type);
 public:
  void writeStrAttr(hid_t grp_id_a, const char *sattr_name_a,
		    const char *sattr_data_a);
  void writeStrAttrArray(hid_t grp_id_a, const char *sattr_name_a,
			 const char *sattr_data_a, 
			 int iDataLength_a,   /* Length of each string, including NULL (must be all the same) */
			 int iSize_a);         /* Number of strings */
  void writeIntAttr(hid_t grp_id_a, const char *sattr_name_a,
		    int iattr_data_a);
  void writeFltAttr(hid_t grp_id_a, const char *sattr_name_a,
		    float fattr_data_a);
  void writeFltAttrArray(hid_t grp_id_a, const char *sattr_name_a,
			 const float fattr_data_a[], int iSize_a );
  void writeUcharDset(hid_t grp_id_a, const char *sdset_name_a, 
		      int ix_size_a, int iy_size_a, const unsigned char *sdset_bufr_a,
		      int lflip_data_a);
  void writeUshortDset(hid_t grp_id_a, const char *sdset_name_a, 
		       int ix_size_a, int iy_size_a, const unsigned char  *sdset_bufr_a,
		       int lflip_data_a);
  void writeIntDset(hid_t grp_id_a, const char *sdset_name_a, 
		    int isize_a, const int *pdset_a);
  void writeFltDset(hid_t grp_id_a, const char *sdset_name_a, 
		    int isize_a, const float *pdset_a);
  
  int readDataTypeDset(hid_t grp_id_a, const char *sdset_name_a,
		       int *idata_type_a);
  int readDataTypeAttr(hid_t grp_id_a, const char *sattr_name_a,
		       int *idata_type_a);
  int readStrAttr(hid_t grp_id_a, const char *sattr_name_a,
		  char *sattr_data_a, int istr_len_a);
  int readStrAttrArray(hid_t grp_id_a, 
		       const char *sattr_name_a,
		       char *sattr_data_a, 
		       int  *piSize_a,       /* Returns the number of elements found */
		       int  iMaxSize_a,      /* The maximum # of elements we can read */
		       int  istr_len_a);     /* Specifies the size of each string */
  int readIntAttr(hid_t grp_id_a, const char *sattr_name_a,
		  int *iattr_data_a);
  int readFltAttr(hid_t grp_id_a, const char *sattr_name_a,
		  float *fattr_data_a);
  int readFltAttrArray(hid_t grp_id_a, const char *sattr_name_a,
		       float fattr_data_a[], int *piSize_a, int iMaxSize_a );
  int readOneDimDsetSize(hid_t grp_id_a, const char *sdset_name_a, 
			 int *ix_size_a);
  int readTwoDimDsetSize(hid_t grp_id_a, const char *sdset_name_a, 
			 int *ix_size_a, int *iy_size_a);
  int readUcharDset(hid_t grp_id_a, const char *sdset_name_a, 
		    unsigned char *sdset_bufr_a, int lflip_data_a);
  int readUshortDset(hid_t grp_id_a, const char *sdset_name_a, 
		     unsigned char *sdset_bufr_a, int lflip_data_a);
  int readIntDset(hid_t grp_id_a, const char *sdset_name_a, 
		  int *sdset_a);
  int readFltDset(hid_t grp_id_a, const char *sdset_name_a, 
		  float *sdset_a);
};

class SigFunc 
{
  private:
    int    lPseudoCappi;
  public:
    int    getObjectType(const struct product_hdr *pprod_hdr_a);
    int    getObjectTypeFromStr(const char *sobject_type_a);
    const char   *getProdType(const struct product_hdr *pprod_hdr_a);
    int    getProdTypeFromStr(const char *sprod_type_a);
    int    lIsPseudoCappi(void);
    float  getProdPar(const struct product_hdr *pprod_hdr_a);
    void   getProdSpecificData(const float fprod_par_a, 
             struct product_hdr *pprod_hdr_a);
    int    lIsTwoByteDataType(int idata_type_a);
    int    lIsProdParValid(int iprod_type_a);
    const  char   *getProdQuantity(const UINT2 idata_out_a);
    int    lIsProdRawQuantityValid(const UINT2 idata_out_a);
    int    getDataTypeFromProdQuantityStr(const char *prod_quanity_a);


    time_t getEpochsTime(const struct ymds_time *ymds_a);
    struct ymds_time getYMDSTimeFromDateTimeStr(const char *sdate_a,
           const char *stime_a);
    char   *getProjFromProjdef(const char *projdef_a);
    float  getLonFromProjdef(const char *projdef_a);
    float  getLatFromProjdef(const char *projdef_a);
};



#define VVP_MAX_INTERVALS     100
#define RAW_HDF5_MAX_MOMENTS  5   //DBZ, VEL, WIDTH, ZDR, SQI
#define MAX_SCANS             (RAW_HDF5_MAX_MOMENTS * MAX_SWEEPS)

/* Version of the H5rad document we are coding to */
#define H5_MAJOR_VERSION 1
#define H5_MINOR_VERSION 2
struct What 
{
  char object[16];
  int  sets;         // Max 1 Image/Composite. Max 50 VVP.
  char version[16];
  char date[16];
  char time[16];
};

struct Where
{
  //IMAGE and COMP. Image and Composite
  char  projdef[160];
  int   xsize;
  int   ysize;
  float xscale;
  float yscale;
  float LL_lon;
  float LL_lat;
  float UR_lon;
  float UR_lat;

  //SCAN and PVOL
  float angle;
  int   lAngleFound;

  //RHI
  float az_angle;
  float range;

  //XSEC
  float start_lon;
  float start_lat;
  float stop_lon;
  float stop_lat;

  //VP. Vertical Profile. Sigmet VVP
  float lon;
  float lat;
  float height;
  int   levels;
  float interval;  

};

struct How
{
  // Top
  int   WMO; 
  char  place[24];
  int   startepochs; 
  int   endepochs; 
  char  system[24];
  char  software[24];
  float beamwidth;
  float wavelength;
  float pulsewidth;
  int   lowprf;
  int   highprf;
  char  nodes[32][N2_MAX_NODE_SIZE];
  int   numNodes;     //Private variable used node count
  float angles[MAX_SWEEPS];  /* Required for RAW, if missing we will estimate */
  int   iNumAngles;   //Number of angles in the above list
  int   lAnglesValid; //Angles and num are valid
  int   doppler;      //Only read for SCAN and PVOL

  int   angleindex;  /* Index of the sweep, only applicable for SCAN type */
  int   lAngleIndexValid;
  float rpm;

  // Vertical Profile (VVP)
  float minrange;
  float maxrange;
  float NI;
  int   dealiased;
};

struct DatasetWhat
{
  char  product[16];
  float prodpar;
  int   prodparvalid; //Private variable
  char  quantity[16];
  char  startdate[16];
  char  starttime[16];
  char  enddate[16];
  char  endtime[16];
  float gain;
  float offset;
  float nodata;
  float undetect;
};

struct ScanWhere
{
  float angle;
  float xscale;
};

struct ScanHow
{
  int   startepochs; 
  int   endepochs; 
  float pulsewidth;
  int   lowprf;
  int   highprf;
  int   angleindex;  /* Required value, if not filled in we will estimate the value */
  int   lAngleIndexValid;
};


struct Image
{
  unsigned char  *pDataBufr;  //Image only
  DatasetWhat    what;
};
#ifdef SIGMET_INGEST_H
struct iris_moment_info
{
  SINT4  idtype;               /* Data type for this moment */
  UINT2  iThresh;              /* Data value which means thresholded */
  UINT2  iNoData;              /* Data value which means area-not-scanned */
  FLT4   fGain;                /* Gain and offset used to convert data to scientific */
  FLT4   fOffset; 
  struct ingest_data_header idhdr;
  UINT1 *pDataBufr;            /* Pointer to buffer with data in it */
  SINT4  iBinCount;            /* Number of range bins in this moment */
  struct ymds_time SweepTime;  /* Sweep start time in IRIS timezone */
};

struct Scan 
{
  unsigned char *pDataBufr;  
  DatasetWhat   what;
  ScanWhere     where;
  ScanHow       how;
  struct iris_moment_info MInfo;
};
#endif  /* #ifdef SIGMET_INGEST_H */

struct Profile //Used in Vertical Profiles (VVP) 
{
  float height[VVP_MAX_INTERVALS];
  float ff[VVP_MAX_INTERVALS];
  float dd[VVP_MAX_INTERVALS];
  float ff_dev[VVP_MAX_INTERVALS];
  float dd_dev[VVP_MAX_INTERVALS];
  int   n[VVP_MAX_INTERVALS];
  float dbz[VVP_MAX_INTERVALS];
  float dbz_dev[VVP_MAX_INTERVALS];
  float z[VVP_MAX_INTERVALS];
  float z_dev[VVP_MAX_INTERVALS];
  float w[VVP_MAX_INTERVALS];
  float w_dev[VVP_MAX_INTERVALS];
  float div[VVP_MAX_INTERVALS];
  float div_dev[VVP_MAX_INTERVALS];
  float def[VVP_MAX_INTERVALS];
  float def_dev[VVP_MAX_INTERVALS];
  float ad[VVP_MAX_INTERVALS];
  float ad_dev[VVP_MAX_INTERVALS];
  float chi2[VVP_MAX_INTERVALS];
  DatasetWhat   what;
};

struct ProfileParms //Used in Vertical Profiles (VVP)
{
  int ff;
  int dd;
  int ff_dev;
  int dd_dev;
  int dbz;
  int dbz_dev;
  int z;
  int z_dev;
  int w;
  int w_dev;
  int div;
  int div_dev;
  int def;
  int def_dev;
  int ad;
  int ad_dev;
  int chi2;
};


#ifdef SIGMET_INGEST_H
//Struct for defining Image/Composite/VVP
struct H5Data 
{
   const struct convert_site_table *pSite;         //Internally used
   const struct convert_task_table *pTask;         //Internally used
   int                  objectType; // _IMAGE, _COMP, _VP _XSEC, _PVOL
   struct What          what;
   struct Where         where;
   struct How           how;
   struct Image         image;                      //Image only
   struct Profile       profile;                    //VVP Only
   struct ProfileParms  profileParms;               //private VVP Only
   struct Scan          scan[MAX_SCANS]; //PVOL (Raw) only
   int    numMomentScans;                           //private. Max is 5  
};
#endif  /* #ifdef SIGMET_INGEST_H */

/* Table used to map HDF5 Places, First elevation angles, and doppler flag to 
 * IRIS task names.  Wild cards are allowed for each input, the
 * list is searched in order.  The first match wins.
 */
struct convert_task_table
{
  char  sHowPlace[16];        /* HDF5 place, null terminated, wildcards allowed */
  char  sHowAreaid[32];       /* HDF5 areaid, null terminated, should be NONE if not used */
  UINT1 lHowDopplerWild;
  UINT1 lHowAngles0Wild;  
  UINT1 lWhereXSizeWild;
  FLT4  lWhereXScaleWild;
  UINT1 lHowDoppler;           /* Task is a Doppler task */
  FLT4  fHowAngles0;      /* First fixed angle, match if difference is <0.09 degree */
  char  sDatasetWhatProduct[16];
  char  sDatasetWhatQuantity[16];
  int   iWhereXSize;
  FLT4  fWhereXScale;
  char  sWhereProjDef[80];

  char  sIrisTaskName[16];     /* IRIS task name to use */
  char  sIrisProductName[16];  /* IRIS product name to use */
};

struct convert_site_table
{
  int   iWMO;
  char  sSystem[16];           /* GEMAxxx, EECxxx, ERICxxx, other */
  char  sIrisSitename16[20];   /* IRIS Sitename, null terminated */
  SINT4 iIrisSiteNumber;       /* IRIS Sitenumber, range 0-30 */
  char  sHowPlace[16];         /* HDF5 place, null terminated */
  char  sHDF5Node[N2_MAX_NODE_SIZE]; /* HDF5 node, null terminated */
  UINT1 lRecordUtc;            /* Recorded time is UTC, else local */
  SINT2 iLocalWest;            /* Local time offset */
  char  sLocalTZName[TZNAME_SIZE]; /* Name of local time */
  FLT4  fZCalib;               /* Calibration reflectivity at 1 km, 1us pw */
};

/* Information from the config file to customize the convertor */
struct convert_config
{
  struct convert_site_table *pSites;  /* Pointer to malloc'ed site list */
  struct convert_task_table *pTasks;  /* Pointer to malloc'ed task list */
  FLT4  fDefaultAngles[ MAX_SWEEPS ];  /* Angles to use for SCAN product if none in file */
  SINT4 iSiteCount;
  SINT4 iTaskCount;
  SINT4 iDefaultAngleCount;
  SINT4 iDopplerTimeOffset;    /* Time in seconds to add to the Doppler nominal time */
  UINT1 lLogToFile;
  UINT1 lLogToTerm;
  UINT1 lVerbose;              /* Log more details */
  UINT1 lVerbose2;             /* Log even more details */
  UINT1 lAppendToLog;          /* Append to previous log file */
  UINT1 lSitesFromStation;     /* Determine IRIS sitename from station ID */
  UINT1 ipad_7x2[2];
  FILE *iLogFile;              /* Open file descriptor to log file */
  FLT4  fDefaultWavelength;
  FLT4  fDefaultPulsewidth;
  FLT4  fDefaultBeamwidth;     /* Beamwidth in degrees */
  SINT4 iDefaultPrf;
};

struct command_line
{
  char  sInFile[FILENAME_SIZE];
  char  sInPath[PATHNAME_SIZE];
  char  sOutPath[PATHNAME_SIZE];
};


#ifdef SIGMET_INGEST_H
struct moment_info
{
  int  iScanIndex;           /* Index into the N2 scans in this file */
};
struct sweep_info
{
  struct moment_info MInfo[RAW_HDF5_MAX_MOMENTS];
};

struct volume_info
{
  struct sweep_info SInfo[MAX_SWEEPS];
  int    iMoments;                /* Number of data moments in the volume scan */
  struct dsp_data_mask DataMask;  /* Summary of data */
};
#endif  /* #ifdef SIGMET_INGEST_H */

#ifdef SIGMET_INGEST_HEADER_DEFINED
/* Functions in HDF5Ingest.C */
MESSAGE ConvertHDF5ToIngestHeader
( const struct H5Data *ph5_data_a,
  struct product_hdr *pprod_hdr_a,
  struct ingest_header *pIHeader_a,
  const struct command_line *pcommand_a, 
  struct volume_info *swp_info_a,
  const char *sPathStart_a,
  const UINT1 lSwpMask_a[MAX_SWEEPS] );

void RemoveIngestFiles
( const struct ingest_header *pIHeader_a,  /* Ingest header */
  const char *sPathStart_a,                /* Start of pathnames */
  const UINT1 lSwpMask_a[MAX_SWEEPS] );    /* Mask of sweeps to do */
#endif  /* #ifdef SIGMET_INGEST_HEADER_DEFINED */

/* Functions in HDF5Subs.C */
const struct convert_site_table *FindSiteByPlace
( const char *sSitename16_a,             /* HDF5 place name, NULL terminated */
  const struct convert_config *pCConfig_a ); /* Configuration */

int FindSiteByNode
( const char *sSitenode_a,               /* HDF5 node name, NULL terminated */
  const struct convert_config *pCConfig_a ); /* Configuration */

#ifdef SIGMET_INGEST_H
const struct convert_task_table *FindTaskByHdf5
( const struct H5Data  *pH5_a,           /* HDF5 structure */
  const struct convert_config *pCConfig_a ); /* Configuration */
#endif  /* #ifdef SIGMET_INGEST_H */

void LoadConfig                         /* File: HDF5Subs.C */
( struct convert_config *pCConfig_a,
  const char* sFile_a,                  /* Filename of config file */
  int iDevice_a );                      /* Device number */

void Lprintf                     
( const struct convert_config *pCConfig_a,
  const char *sString_a );

#undef EXTERN
#endif



