/** @file
 */
#include <stdio.h>
#include "grib2.h"

#define MAPSEC1LEN 13

//$$$  SUBPROGRAM DOCUMENTATION BLOCK
//                .      .    .                                       .
// SUBPROGRAM:    g2_create 
//   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
//
// ABSTRACT: This routine initializes a new GRIB2 message and packs
//   GRIB2 sections 0 (Indicator Section) and 1 (Identification Section).
//   This routine is used with routines "g2_addlocal", "g2_addgrid", 
//   "g2_addfield", and "g2_gribend" to create a complete GRIB2 message.  
//   g2_create must be called first to initialize a new GRIB2 message.
//   Also, a call to g2_gribend is required to complete GRIB2 message
//   after all fields have been added.
//
// PROGRAM HISTORY LOG:
// 2002-10-31  Gilbert
//
// USAGE:    int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
//   INPUT ARGUMENTS:
//     cgrib    - Character array to contain the GRIB2 message
//     listsec0 - Contains information needed for GRIB Indicator Section 0.
//                Must be dimensioned >= 2.
//                listsec0[0]=Discipline-GRIB Master Table Number
//                            (see Code Table 0.0)
//                listsec0[1]=GRIB Edition Number (currently 2)
//     listsec1 - Contains information needed for GRIB Identification Section 1.
//                Must be dimensioned >= 13.
//                listsec1[0]=Id of orginating centre (Common Code Table C-1)
//                listsec1[1]=Id of orginating sub-centre (local table)
//                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
//                listsec1[3]=GRIB Local Tables Version Number (Code Table 1.1)
//                listsec1[4]=Significance of Reference Time (Code Table 1.2)
//                listsec1[5]=Reference Time - Year (4 digits)
//                listsec1[6]=Reference Time - Month
//                listsec1[7]=Reference Time - Day
//                listsec1[8]=Reference Time - Hour
//                listsec1[9]=Reference Time - Minute
//                listsec1[10]=Reference Time - Second
//                listsec1[11]=Production status of data (Code Table 1.3)
//                listsec1[12]=Type of processed data (Code Table 1.4)
//
//   OUTPUT ARGUMENTS:      
//     cgrib    - Char array to contain the new GRIB2 message.
//                Must be allocated large enough to store the entire
//                GRIB2 message.
//
//   RETURN VALUES:
//     ierr     - return code.
//              > 0 = Current size of new GRIB2 message
//               -1 = Tried to use for version other than GRIB Edition 2
//
// REMARKS: This routine is intended for use with routines "g2_addlocal", 
//          "g2_addgrid", "g2_addfield", and "g2_gribend" to create a complete 
//          GRIB2 message.
//
// ATTRIBUTES:
//   LANGUAGE: C
//   MACHINE:  
//
//$$$
g2int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
{

      g2int  ierr;
      g2int   zero=0,one=1;
      g2int   mapsec1len=MAPSEC1LEN;
      g2int   mapsec1[MAPSEC1LEN]={ 2,2,1,1,1,2,1,1,1,1,1,1,1 };
      g2int   i,lensec0,lensec1,iofst,ibeg,nbits,len;

      ierr=0;
//
//  Currently handles only GRIB Edition 2.
//  
      if (listsec0[1] != 2) {
        printf("g2_create: can only code GRIB edition 2.");
        ierr=-1;
        return (ierr);
      }
//
//  Pack Section 0 - Indicator Section 
//  ( except for total length of GRIB message )
//
      cgrib[0]=0x47;   // 'G'            // Beginning of GRIB message
      cgrib[1]=0x52;   // 'R'
      cgrib[2]=0x49;   // 'I'
      cgrib[3]=0x42;   // 'B'
      sbit(cgrib,&zero,32,16);           // reserved for future use
      sbit(cgrib,listsec0+0,48,8);       // Discipline
      sbit(cgrib,listsec0+1,56,8);       // GRIB edition number
      lensec0=16;      // bytes (octets)
//
//  Pack Section 1 - Identification Section
//
      ibeg=lensec0*8;        //   Calculate offset for beginning of section 1
      iofst=ibeg+32;         //   leave space for length of section
      sbit(cgrib,&one,iofst,8);     // Store section number ( 1 )
      iofst=iofst+8;
      //
      //   Pack up each input value in array listsec1 into the
      //   the appropriate number of octets, which are specified in
      //   corresponding entries in array mapsec1.
      //
      for (i=0;i<mapsec1len;i++) {
        nbits=mapsec1[i]*8;
        sbit(cgrib,listsec1+i,iofst,nbits);
        iofst=iofst+nbits;
      }
      //
      //   Calculate length of section 1 and store it in octets
      //   1-4 of section 1.
      //
      lensec1=(iofst-ibeg)/8;
      sbit(cgrib,&lensec1,ibeg,32);
//
//  Put current byte total of message into Section 0
//
      sbit(cgrib,&zero,64,32);
      len=lensec0+lensec1;
      sbit(cgrib,&len,96,32);

      return (len);

}
