#include <stdio.h>
#include "grib.h"
#include "gdecode.h"

#define BUFLEN 32000000

#ifdef REAL_8
typedef double FORTRAN_real;
#else
typedef float FORTRAN_real;
#endif

fortint getIntegerValue(gribProduct**,unsigned char*);

#ifdef __uxp__
MAIN__( int argc, char ** argv)
#else
main( int argc, char ** argv)
#endif
{
FILE * in;
fortint status;
unsigned char buffer[BUFLEN];
fortint bufferlen;
fortint oldpos= 0, pos, prodlen;
fortint GRIBcount = 0;
fortint type, table, param, levty, level1, level2, level, date;
fortint time, step;
union {
  fortint number;
  char characters[5];
} expver;
char * months[12] = { " January ",
                      " February",
                      "  March  ",
                      "  April  ",
                      "   May   ",
                      "   June  ",
                      "   July  ",
                      "  August ",
                      "September",
                      " October ",
                      " November",
                      " December"};

  if ( argc != 2 ) {
    printf(" Usage: GRIB_profile filename\n");
    exit(1);
  }

  in = fopen( argv[1], "r");
  if ( in == NULL ) {
    perror("GRIB_profile: fopen failed!");
    exit(1);
  }

/*
printf("Number Type    Offset   Length  Param    Level      Date    Time  Step Expver\n");
printf("------ ----    ------   ------ -------  -----  --------   ----  ---- ------\n");
*/

/*
// Loop through products in the file
*/
  do {
    bufferlen = sizeof(buffer);
    status = readany( in, buffer, &bufferlen);

/*
// Accept product if OK or if only problem is 'buffer too small'
*/
    if ( status == -1 ) exit(0);
/*
// Note the product byte offset in the file
*/
    pos = ftell( in );
    prodlen = bufferlen;
    oldpos = pos - prodlen;
    GRIBcount++;

/*
// If it's a GRIB product, pick up more information (parameter,level,..)
*/
    if ( strncmp( buffer, "GRIB", 4) == 0 ) {
      gribProduct * grib;

      GDECODE(&grib,buffer);
      printf("%5d  ", GRIBcount);
      type   = getIntegerValue(&grib,"ecmwfType");
      param  = getIntegerValue(&grib,"parameter");
      levty  = getIntegerValue(&grib,"typeOfLevel");
      level1 = getIntegerValue(&grib,"topLayer");
      level2 = getIntegerValue(&grib,"bottomLayer");
      level  = getIntegerValue(&grib,"pressureLevel");
      date   = getIntegerValue(&grib,"date");
      time   = getIntegerValue(&grib,"time");
      step   = getIntegerValue(&grib,"timeStep");
      table  = getIntegerValue(&grib,"codeTable");

      if( type != -999999)
        printf(" %02d   %8d %8d", type, oldpos, prodlen);
      else
        printf(" --   %8d %8d", oldpos, prodlen);

      printf("  %03d.%03d  ", param, table);

      switch( (int) levty ) {

        case 101:
        case 104:
        case 106:
        case 108:
        case 110:
        case 112:
        case 114:
        case 116:
        case 120:
        case 121:
        case 128:
        case 141:
          printf("%03d-%03d", level1, level2);
          if( date < 13 )
            printf(" %10.9s",months[date-1]);
          else
            printf("   %08d", date);
          break;

        default:
          printf(" %5d", level);
          if( date < 13 )
            printf(" %10.9s",months[date-1]);
          else
            printf("   %08d", date);
          break;

      }
      if( time == -1 )
        printf("  ----", time);
      else
        printf("  %04d", time);
      printf("  %4d", step);
      if( type != -999999) {
        expver.number = getIntegerValue(&grib,"ecmwfExperimentVersionNumber");
#ifdef LITTLE_ENDIAN
        swap4_(&expver);
#endif
        expver.characters[4] = '\0';
        printf("  %4s", &expver.characters);
      }
      else
        printf("  ----");
    }
    else
    {
      buffer[4] = '\0';
      printf("%5d  ", GRIBcount);
      printf("%4s  %8d %8d", buffer, oldpos, prodlen);
    }

    if( (status != 0) && (status != -3) )
      printf("  (%2d)\n", status);
    else
      printf("\n");
        
  } while ( (! feof(in)) && ( status != -1) );

    fclose(in);
}
