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

#include "fortint.h"
#include "movebytes.h"

#define BUFFLEN 1000000
#define PADBUFFLEN 1000000
#define OK 0
#define ENDOFFILE -1
#define BUFFERTOOSMALL -3

#define ONEBYTEINT(a)   (fortint) ( *(a) )
#define TWOBYTEINT(a)   (fortint) ( (*(a))<<8 | (*((a)+1))<<0 )
#define THREEBYTEINT(a) (fortint) (TWOBYTEINT((a))<<8 | (*((a)+2))<<0 )
#define FOURBYTEINT(a)  (fortint) (THREEBYTEINT((a))<<8 | (*((a)+3))<<0 )

fortint readgrib( FILE * , char * ,fortint * );

int main(int argc, char ** argv ) {
FILE * inFile, * outFile;
unsigned char * buffer;
fortint bufsize = BUFFLEN;
fortint loop, size, newlen, buflen, status, productNumber = 0, stream;
fortint lastGribEnd = 0, currentGribStart = 0;
fortint paddingLength, currentGribLength;
unsigned char paddingBuffer[PADBUFFLEN];

  if( argc < 3) {
    printf("Usage: changeStream stream sourceFile targetFile\n");
    exit(1);
  }

  if( (inFile = fopen(argv[2],"r")) == NULL ) {
    printf("Problem opening file %s for reading\n",argv[2]);
    exit(1);
  }

  if( (outFile = fopen(argv[3],"w")) == NULL ) {
    printf("Problem opening file %s for reading\n",argv[3]);
    exit(1);
  }

   buffer = (unsigned char *) malloc(bufsize);
   if( buffer == NULL ) {
    printf("Problem with malloc for GRIB buffer\n");
    exit(1);
  }

  for( loop = 0; loop < PADBUFFLEN; loop++ ) paddingBuffer[loop] = '\0';

  stream = atol(argv[1]);

  do {
    lastGribEnd = ftell(inFile);
    buflen = bufsize;
    status = (fortint) readgrib(inFile,(char *)buffer,(fortint *)&buflen);

    switch( status ) {

      case OK:
        productNumber++;
        currentGribLength = THREEBYTEINT(&buffer[4]);
        currentGribStart = ftell(inFile) - currentGribLength;
        paddingLength = currentGribStart - lastGribEnd;
        if( paddingLength ) {
          size = fwrite(paddingBuffer,(size_t)1,(size_t)paddingLength,outFile);
          if( size != paddingLength ) {
            printf("Problem writing padding bytes to file %s\n", outFile);
            exit(1);
          }
        }
        MOVE2BYTES(&buffer[51],&stream);
        size = fwrite(buffer, (size_t) 1, (size_t) buflen, outFile);
        if( size != buflen ) {
          printf("Problem writing to file %s\n", outFile);
          exit(1);
        }
        break;

      case ENDOFFILE:
        currentGribStart = ftell(inFile);
        paddingLength = currentGribStart - lastGribEnd;
        if( paddingLength ) {
          size = fwrite(paddingBuffer,(size_t)1,(size_t)paddingLength,outFile);
          if( size != paddingLength ) {
            printf("Problem writing padding bytes to file %s\n", outFile);
            exit(1);
          }
        }
        break;

      case BUFFERTOOSMALL:
        printf("Buffer too small\n");
        exit(1);

      default:
        printf("Problem reading GRIB product; status = %d\n", status);
        exit(1);

    }

  } while( status == 0 );

  exit(0);

}
