/** @file
 * @brief Unpack Section 7 (Data Section) as defined in GRIB Edition 2.
 * @author Stephen Gilbert @date 2002-10-31
 */
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include "grib2.h"

g2int simunpack(unsigned char *,g2int *, g2int,g2float *);
int comunpack(unsigned char *,g2int,g2int,g2int *,g2int,g2float *);
g2int specunpack(unsigned char *,g2int *,g2int,g2int,g2int, g2int, g2float *);
#ifdef USE_PNG
g2int pngunpack(unsigned char *,g2int,g2int *,g2int, g2float *);
#endif  /* USE_PNG */
#if defined USE_JPEG2000 || defined USE_OPENJPEG
g2int jpcunpack(unsigned char *,g2int,g2int *,g2int, g2float *);
#endif  /* USE_JPEG2000 */

/**
 *
 * This subroutine unpacks Section 7 (Data Section) as defined in GRIB
 * Edition 2.
 *
 * PROGRAM HISTORY LOG:
 * - 2002-10-31  Gilbert
 * - 2002-12-20  Gilbert - Added GDT info to arguments
 *                       and added 5.51 processing.
 * - 2003-08-29  Gilbert  - Added support for new templates using
 *                        PNG and JPEG2000 algorithms/templates.
 * - 2004-11-29  Gilbert  - JPEG2000 now allowed to use WMO Template no. 5.40
 *                        PNG now allowed to use WMO Template no. 5.41
 * - 2004-12-16  Taylor   - Added check on comunpack return code.
 * - 2008-12-23  Wesley   - Initialize Number of data points unpacked
 *
 * @param cgrib char array containing Section 7 of the GRIB2 message
 * @param iofst Bit offset of the beginning of Section 7 in cgrib.
 * @param igdsnum Grid Definition Template Number (see Code Table 3.0)
 * (Only used for DRS Template 5.51)
 * @param igdstmpl Pointer to an integer array containing the data
 * values for the specified Grid Definition Template (N=igdsnum). Each
 * element of this integer array contains an entry (in the order
 * specified) of Grid Definition Template 3.N. (Only used for DRS
 * Template 5.51).
 * @param idrsnum Data Representation Template Number (see Code Table 5.0)
 * @param idrstmpl Pointer to an integer array containing the data
 * values for the specified Data Representation Template
 * (N=idrsnum). Each element of this integer array contains an entry
 * (in the order specified) of Data Representation Template 5.N
 * @param ndpts Number of data points unpacked and returned.
 * @param fld Pointer to a float array containing the unpacked data
 * field.
 *
 * @return
 * - 0 no error
 * - 2 Not section 7
 * - 4 Unrecognized Data Representation Template
 * - 5 need one of GDT 3.50 through 3.53 to decode DRT 5.51
 * - 6 memory allocation error
 * - 7 corrupt section 7.
 *
 * @author Stephen Gilbert @date 2002-10-31
 */
g2int
g2_unpack7(unsigned char *cgrib, g2int *iofst, g2int igdsnum, g2int *igdstmpl,
           g2int idrsnum, g2int *idrstmpl, g2int ndpts, g2float **fld)
{
    g2int ierr,isecnum;
    g2int ipos,lensec;
    g2float *lfld;

    ierr=0;
    *fld=0;     /*NULL*/

    gbit(cgrib,&lensec,*iofst,32);        /* Get Length of Section */
    *iofst=*iofst+32;
    gbit(cgrib,&isecnum,*iofst,8);         /* Get Section Number */
    *iofst=*iofst+8;

    if ( isecnum != 7 ) {
        ierr=2;
        /*fprintf(stderr,"g2_unpack7: Not Section 7 data.\n"); */
        return(ierr);
    }

    ipos=(*iofst/8);
    lfld=(g2float *)calloc(ndpts ? ndpts : 1,sizeof(g2float));
    if (lfld == 0) {
        ierr=6;
        return(ierr);
    }
    else {
        *fld=lfld;
    }

    if (idrsnum == 0)
        simunpack(cgrib+ipos,idrstmpl,ndpts,lfld);
    else if (idrsnum == 2 || idrsnum == 3) {
        if (comunpack(cgrib+ipos,lensec,idrsnum,idrstmpl,ndpts,lfld) != 0) {
            return 7;
        }
    }
    else if (idrsnum == 50) {            /* Spectral Simple */
        simunpack(cgrib+ipos,idrstmpl,ndpts-1,lfld+1);
        rdieee(idrstmpl+4,lfld+0,1);
    }
    else if (idrsnum == 51)              /* Spectral complex */
        if ( igdsnum>=50 && igdsnum <=53 )
            specunpack(cgrib+ipos,idrstmpl,ndpts,igdstmpl[0],igdstmpl[2],igdstmpl[2],lfld);
        else {
            fprintf(stderr,"g2_unpack7: Cannot use GDT 3.%d to unpack Data Section 5.51.\n",(int)igdsnum);
            ierr=5;
            if ( lfld != 0 ) free(lfld);
            *fld=0;     //NULL
            return(ierr);
        }
#if defined USE_JPEG2000 || defined USE_OPENJPEG
    else if (idrsnum == 40 || idrsnum == 40000) {
        jpcunpack(cgrib+ipos,lensec-5,idrstmpl,ndpts,lfld);
    }
#endif  /* USE_JPEG2000 */
#ifdef USE_PNG
    else if (idrsnum == 41 || idrsnum == 40010) {
        pngunpack(cgrib+ipos,lensec-5,idrstmpl,ndpts,lfld);
    }
#endif  /* USE_PNG */
    else {
        fprintf(stderr,"g2_unpack7: Data Representation Template 5.%d not yet implemented.\n",(int)idrsnum);
        ierr=4;
        if ( lfld != 0 ) free(lfld);
        *fld=0;     /* NULL */
        return(ierr);
    }

    *iofst=*iofst+(8*lensec);

    return(ierr);    /* End of Section 7 processing */
}
