/*************************************************************************/
/*  name - rdssmi                     
 *
 *  Purpose - This program reads liquid water and water vapor 
 *            Monthly HDF files
 *
 *  Input - HDF file name and output file name
 *  Output - Report file 
 *
 *  Key Local Parameters - maxrank - max rank of HDF SDS
 *                         hdfname - name of HDF file
 *                         begin1 - beginning cell number
 *                         end1 - ending cell number
 *                         dataitems - data items to be read
 *                         status - input ok or not
 *
 * Functions Called -     
 *                        getinput - gets data date and file type
 *                        readhdf - reads file id and description, etc.
 *                        getdata - gets parameters to subset
 *                        readdata - reads data, max, mins, etc
 *************************************************************************/

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "hdf.h"

#define MAXRANK    2
#define LISTSIZE   55
#define FIRST      1
#define MAXLEN     256
#define MAXLNG     132
#define STARTPOS   1

int main(argc,argv)

int argc;
char **argv;

{

 int status, iret;
 char ddate[5], type[2], hdfname[36], outfile[50], subset_ans[2], contkey[2];
 int begin1, end1, begin2, end2;
 unsigned short int dataitems[LISTSIZE];
 FILE *out;

 /*  function prototypes */

 char *getinput();
 void readhdf();
 void getarea();
 void getdata();
 void readdata();

/* Try to extract date and file type from command line */
 status = FALSE;
 if (argc == 3){
   strcpy(hdfname,argv[1]);
   if (strcmp(argv[2],"-") == 0) {
     strcpy(outfile,"stdout");
   } else {
     strcpy(outfile,argv[2]);
   }
 }

 else  /*  prompt for info if necessary */

 {
   printf("This program reads the cloud liquid water and integrated ");
   printf("water vapor Monthly HDF files\n");
   getinput(hdfname,outfile);
  }


  printf("Input file is %s\n",hdfname);
  printf("Output file is %s\n\n",outfile);

/* open output file */

  if (strcmp(outfile,"stdout") == 0) {
    out = stdout;
  }
  else
  {
    if ((out=fopen(outfile,"wt")) == NULL)
    {
      printf("Cannot open output file %s\n\n",outfile);
      exit(1);
    }
  }
  
/*  call function to read file id */

  readhdf(out,hdfname);

/*  call function to subset area */

  getarea(subset_ans,&begin1,&end1,&begin2,&end2);

/*  call function to get parameters */

  getdata(out,hdfname,dataitems);

/*  call function to read data */

  printf("\n\nGetting data, Please wait ...\n");
  readdata(out,hdfname,dataitems,subset_ans,begin1,end1,begin2,end2);
  fprintf(stderr,
          "\n***************************************************************\n");
  fprintf(stderr,
          "*                                                             *\n");
  fprintf(stderr,
          "*         Program has completed processing                    *\n");
  fprintf(stderr,
          "*                                                             *\n");
  fprintf(stderr,
          "***************************************************************\n");

}
/***********************************************************************/
/*   name - getinput  
 *
 *   Purpose - This subroutine accepts user input for the input & output
 *             file names
 *
 *   Input parameters -  none
 *   Output parameters - hdfname - input file name
 *                       outfile - output file name. If = '-' then prints
 *                                 to standard output (stdout)
 *
 *  Key Local Parameters - NONE
 *  Functions Called - NONE
 ************************************************************************/
  
 char *getinput(hdfname,outfile)
 char *hdfname,*outfile;

 {
  do {
    printf("Please enter file name to read: ");
    scanf("%s",hdfname);
    printf("\n\n");
  } while (strlen(hdfname) == 0);

  
  do {
    printf("please enter report file name (use `-' to print to screen): ");
    scanf("%s",outfile);
    if (*outfile == '-') strcpy(outfile,"stdout");
    printf("\n\n");
  } while (strlen(outfile) == 0);

}

/*******************************************************************/
/*  name - readhdf                              
 *
 * Purpose - This subroutine reads the file id and file description
 *
 * Input -   hdfname - the name of the HDF input file
 *
 * Key Local Parameters :  iret - return code from HDF routines
 *                         dfile - pointer to HDF file
 *                         id - file id
 *                         filedesc - file description
 *
 * Functions Called :  HDF functions to get file id, file description,
 *******************************************************************/

 void readhdf(out,hdfname)

 char *hdfname;
 FILE *out;

 {

  int iret,dfile;
  char fileid[255];

  dfile = Hopen(hdfname,DFACC_READ,0);
  if (dfile == -1){
    fprintf(out,"%s %s\n\n","Error in opening HDF file",hdfname);
    exit(1);
  }

 /* get file id */

  iret = DFANgetfidlen(dfile,FIRST);
  if (iret == -1) {
    printf("File doesn't have a file identifier\n");
  }
  else
  {
    iret = DFANgetfid(dfile,fileid,MAXLEN,FIRST);
    if (iret == -1){
      fprintf(out,"%s%d\n\n","Error in getting file id: id = ",dfile);
      exit(1);
    }
    else
    fprintf(out,"%s %s\n\n","File ID: ",fileid);

    iret = Hclose(dfile);

   }
}
/********************************************************************/
/*  Name - getarea                       type - function                    
 *                                                                       
 * Purpose - This functions asks the user to enter the cell      
 *           numbers to subset data          
 *                                                                      
 * Input Parameters - NONE                                              
 * Output Parameters -subset_ans - enter cell number(C) or none
 *                    begin1-beginning cell number               
 *                    end1 - ending cell number                       
 *                                                                      
 * Key Local Parameters -NONE
 *
 * Functions Called - NONE
 *****************************************************************/

 void getarea(subset_ans,begin1,end1,begin2,end2)

 char *subset_ans;
 int *begin1, *end1, *begin2, *end2;
 {
  char kind[2];

  printf("Enter whether you would like to further subset based on lat/lon?\n");
  printf("yes (Y) or no subsetting (N): ");
  scanf("%s",kind);
  *subset_ans = toupper(kind[0]);
  
  if (subset_ans[0] == 'N'){
    *begin1 = 1;
    *end1 = 180;
    *begin2 = 1;
    *end2 = 360;
  }
  else {
    
     printf("\n\nEnter beginning and end latitude (1 = North 180 = south) ");
     printf("separated by a space\n Use whole numbers from 1 to 180:  ");
     scanf("%d %d",begin1,end1);
     while ((*begin1<1) || (*begin1 > 180) || (*end1 > 180) || (*end1 < 1) || 
            (*end1<*begin1)) {
       printf(" Incorreect entry - please try again.\n");
       printf("\n\nEnter beginning and end latitude (1 = North 180 = south) ");
       printf("separated by a space\n Use whole numbers from 1 to 180:  ");
       scanf("%d %d",begin1,end1);
     }
       
     printf("\n\nEnter beginning and end longitude (1 = West 360 = East) ");
     printf("separated by a space\n Use whole numbers from 1 to 360:  ");
     scanf("%d %d",begin2,end2);
     while ((*begin2<1) || (*begin2 > 360) || (*end2 > 360) || (*end2 < 1) ||
            (*end2<*begin2)) {
       printf(" Incorreect entry - please try again.\n");
       printf("Enter beginning and end longitude (1 = West 360 = East) ");
       printf("separated by a space\n Use whole numbers from 1 to 360:  ");
       scanf("%d %d",begin2,end2);
     }
  }
}


/*********************************************************************/
/*  Name - getdata
 *
 * Purpose - This subroutine allows the user to choose from the annotation
 *           labels, which data parameters to dump
 *
 * Input -   hdfname - the number of HDF file
 * Output -  dataitems - list of reference numbers of data to dump 
 *
 * Key Local Parameters - nlabels - number of reference labels
 *                        i,j - counters
 *                        k - index to dataitems
 *                        itemnum - number for user to choose
 *                        startpos - starting position in HDF file
 *                        reflist - list of reference numbers
 *                        labellist - list of annotation labels
 *            
 * Functions called - annotation label routines from HDF
 *********************************************************************/

void getdata(out,hdfname,dataitems)

char *hdfname;
unsigned short int dataitems[LISTSIZE];
FILE *out;

{
  int i,j,k,itemnum,nlabels,iret;
  char labellist[LISTSIZE*MAXLNG];
  unsigned short int reflist[LISTSIZE];
  char dataunt[25], datafmt[10], coordsys[25];
  int32 dims[MAXRANK],dimsize[MAXRANK], numdims,numtype;

/*  initialize dataitems array */

  for (i=0; i<LISTSIZE; i++){
     dataitems[i] = 65535;
  }

/*  get annotation labels */

  nlabels  = DFANlablist(hdfname,DFTAG_SD,reflist,labellist,LISTSIZE,
                         MAXLNG,STARTPOS);

  if (nlabels == -1){
    fprintf(out,"Error in getting annotation labels\n\n");
    exit(1);
  }
  
  for (i=0; i<nlabels; ++i){
    if (strcmp(labellist + (i*MAXLNG),"\0") == 0) {
      DFSDgetdims(hdfname,(intn*) &numdims,dimsize,MAXRANK);
      iret = DFSDgetdatastrs(labellist+(i*MAXLNG),dataunt,datafmt,coordsys);
    }
  }
      
  printf("\n");

  j=1;
  k=0;
  for (i=0; i<nlabels; ++i){
    if (j == 1)
    {
      itemnum = 1;
      printf("Item DIMS                         Label\n\n");
    }
    DFSDgetdims(hdfname,(intn*) &numdims,dimsize,MAXRANK);
    if (strcmp(labellist + (i*MAXLNG),"\0") == 0) {
      iret = DFSDgetdatastrs(labellist+(i*MAXLNG),dataunt,datafmt,coordsys);
    }
    printf(" %2d (%dX%d)  %s\n",i+1,dimsize[0],dimsize[1],labellist+(i*MAXLNG));
    j++;
    if (j>15 || (i == nlabels - 1))
    {
      printf("\n");
      printf("Please choose the numbers of the data items to dump ");
      printf("separated by a space.\n");
      printf("Enter -1 to continue to the next list or 0 to quit ");
      printf("entering parameters\n\n");
      
      while (itemnum >0)
      {
         scanf("%d",&itemnum);
         if (itemnum == -1)
           break;
         if (itemnum == 0)
         {
           dataitems[k] = 0;
           return;
         }
         dataitems[k] = reflist[itemnum-1];
         k++;
       } /* itemnum > 0 */
       j = 1; 
     }
   } /* end for i<numitems */

   dataitems[k] = 0;
}

/***********************************************************************/
/* Name - readdata
 *                                                                         
 * Purpose - This function determines the data slice to retrieve and using
 *           the reference numbers gets the appropriate data, data        
 *           attributes, max, and min  and then prints the data.          
 *                                                                        
 * Input Parameters - hdfname - name of hdf file to read                  
 *                    dataitems- stores reference numbers of data chosen  
 *                    subset_ans-type of subsetting (cell # or none) 
 *                    begin1- beginning cell number                   
 *                    end1- ending cell number                         
 *                                                                       
 *  Output Parameters - none                                               
 *                                                                         
 * Key Local Parameters - winst - stores starting dimensions of data slice
 *                        windims- stores length of slice                 
 *                        dims - stores dimension of data array
 *                        data - stores data gotten from HDF file               
 *                        datalabel - stores label for data               
 *                        dataunit- stores units for data
 *                        datafmt - stores format for data                
 *                        max,imax - stores maximum value                      
 *                        min,imin - stores minimum value                      
 *                        dataval,idataval - stores data values 
 *                        numdims - number of dimensions of SDS
 *                        dimsize - dimension sizes
 *                        listsize - the max number of parameters
 *                        numtype - HDF number type, 5 floating, 24 -
 *                                  32 bit integer  
 *                                                                        
 * Subroutines Called - HDF routines to read the SDS data slice, max,min  
 *                       data attributes, etc.
 **************************************************************************/          

 void readdata(out,hdfname,dataitems,subset_ans,begin1,end1, begin2, end2)

 char *hdfname, *subset_ans;
 int begin1, end1, begin2, end2;
 FILE *out;
 unsigned short int dataitems[LISTSIZE];

{

 char datalabel[260], dataunt[25], datafmt[10], coord_sys[25];
 int32 iret, winst[MAXRANK], winend[MAXRANK], windims[MAXRANK];
 int32 dims[MAXRANK],dimsize[MAXRANK], numdims,numtype;
 float max, min, datavals[204476],fill_value;
 int k=0,i,j,iendvl1,iendvl2,index;


 /*  set up slice of data */

  winst[1] = begin2;
  winst[0] = begin1;
  winend[1] = end2;
  winend[0] = end1;
  windims[1] = (end2- begin2 + 1);
  windims[0] = (end1-begin1 + 1);
  dims[0] = windims[0];
  dims[1] = windims[1];

 /* get fill value - currently only in ref #2 - but intended to
    apply to all data in file */
 iret = DFSDreadref(hdfname,(uint16) 2);
 iret = DFSDgetdims(hdfname,(intn*) &numdims,dimsize,MAXRANK);
 iret = DFSDgetfillvalue((VOIDP) &fill_value);
 if (iret == -1) {
   printf("FAILED TO GET FILL VALUE - will use 999.989990\n");
   fill_value = 999.989990;
 }

 /*  while we have data items to get */
 k=0;
 while (dataitems[k] != 0)
 {

 /*  go to desired data reference */

  iret = DFSDreadref(hdfname,dataitems[k]);
  if (iret == -1)
  {
   fprintf(out,"Error on going to specified reference number %d\n\n",
           dataitems[k]);
   exit(1);
  }

 /* get data dimensions */

  iret = DFSDgetdims(hdfname,(intn*) &numdims,dimsize,MAXRANK);

  if (iret !=0)
  {
   fprintf(out,"Error on getting data dimensions\n\n");
   exit(1);
  }
  else
  {
   fprintf(out,"Dimensions are %d by %d\n\n",dimsize[0],dimsize[1]);
  }

 /*  get number type */

  iret = DFSDgetNT(&numtype);
  if (iret != 0)
  {
   fprintf(out,"Error on getting number type\n\n");
   exit(1);
  }

 /*  get data attributes */

  iret = DFSDgetdatastrs(datalabel,dataunt,datafmt,coord_sys);
  if (iret != 0)
  {
   fprintf(out,"Error on getting data attributes\n\n");
   exit(1);
  }
  else
  {
   fprintf(out,"Data attributes are as follows:\n\n");
   fprintf(out,"Label            : %s\n\n",datalabel);
   fprintf(out,"Units            : %s\n",dataunt);
   fprintf(out,"Format           : %s\n",datafmt);
   fprintf(out,"Fill Value       : %f\n\n",fill_value);
   fprintf(out,"Coordinate System: %s\n\n",coord_sys);
  }

   iret = DFSDgetrange((VOIDP) &max,(VOIDP) &min);
   if (iret == -1)
   {
    fprintf(out,"Error on getting max and min\n\n");
    exit(1);
   }
   else
   {
    fprintf(out,"Data max: %f\n",max);
    fprintf(out,"Data min: %f\n\n",min);
   }

 /*  get data slice */

   iret = DFSDgetslice(hdfname,winst,windims,(VOIDP) datavals,dims);
   if (iret == -1)
   {
    fprintf(out,"Error on getting data slice\n\n");
    exit(1);
   }
   fprintf(out,
    "Data values for each degree of latitude from %d to %d for longitudes\n",
    winst[0],winend[0]);
   fprintf(out,
    "from %d to %d are:\n\n", winst[1],winend[1]);

   iendvl1 = dims[0];
   iendvl2 = dims[1];

/* print data */
   for (i=0; i<iendvl1; i++){
     for (j=0; j<iendvl2; j++){
        index = i*iendvl2+j;
        fprintf(out,"%12.6f",datavals[index]);
        if (((j+1)%6) == 0){
         fprintf(out,"\n");
        }
     }
     fprintf(out,"\n\n");
    
  }
  k++;
 }  /*  while (dataitems[k] != 0) */
}  /* end readdata */
