/*
 * © Copyright 1996-2012 ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

/************************************************************

 RDB package

 B.Raoult Wed Apr 17 16:07:11 BST 1991

 Definition of the BUFR format.

*************************************************************/


#define BUFR_TYPE_TRACK     40

#ifdef LITTLE_END
#define KEY_TYPE(k)         ((unsigned int)k->header.type)
#define KEY_SUBTYPE(k)      ((unsigned int)k->header.subtype)
#define KEY_YEAR(k)         ((unsigned int)getbits( (unsigned char*)k->header.date_time,  0, 12 ))
#define KEY_MONTH(k)        ((unsigned int)getbits( (unsigned char*)k->header.date_time, 12,  4 ))
#define KEY_DAY(k)          ((unsigned int)getbits( (unsigned char*)k->header.date_time, 16,  6 ))
#define KEY_HOUR(k)         ((unsigned int)getbits( (unsigned char*)k->header.date_time, 22,  5 ))
#define KEY_MINUTE(k)       ((unsigned int)getbits( (unsigned char*)k->header.date_time, 27,  6 ))
#define KEY_SECOND(k)       ((unsigned int)getbits( (unsigned char*)k->header.date_time, 33,  6 ))
#else
#define KEY_TYPE(k)         (k->header.type)
#define KEY_SUBTYPE(k)      (k->header.subtype)
#define KEY_YEAR(k)         (k->header.year)
#define KEY_MONTH(k)        (k->header.month)
#define KEY_DAY(k)          (k->header.day)
#define KEY_HOUR(k)         (k->header.hour)
#define KEY_MINUTE(k)       (k->header.minute)
#define KEY_SECOND(k)       (k->header.second)
#endif

#define KEY_CORR1(k)        CORR_CORR(k->corr1)
#define KEY_CORR2(k)        CORR_CORR(k->corr2)
#define KEY_CORR3(k)        CORR_CORR(k->corr3)
#define KEY_CORR4(k)        CORR_CORR(k->corr4)
#define KEY_IDENT(k)        ((char*)k+15)
#define KEY_LATITUDE(k)     ((unsigned long)getbits((unsigned char*)k,88,25))
#define KEY_LATITUDE1(k)    ((unsigned long)getbits((unsigned char*)k,88,25))
#define KEY_LATITUDE2(k)    ((unsigned long)getbits((unsigned char*)k,152,25))

#ifdef LITTLE_END
#define SET_KEY_LENGTH(k,v) (k).length[0]=(unsigned char)((v)/256);(k).length[1]=(unsigned char)((v)%256);
#else
#define SET_KEY_LENGTH(k,v) (k).length = (v)
#endif

#define KEY_LONGITUDE(k)    ((unsigned long)getbits((unsigned char*)k,56,26))
#define KEY_LONGITUDE1(k)   ((unsigned long)getbits((unsigned char*)k,56,26))
#define KEY_LONGITUDE2(k)   ((unsigned long)getbits((unsigned char*)k,120,26))
#define KEY_NOBS(k)         ((unsigned long)getbits((unsigned char*)k,184,8))
#define KEY_PART1(k)        CORR_PART(k->corr1)
#define KEY_PART2(k)        CORR_PART(k->corr2)
#define KEY_PART3(k)        CORR_PART(k->corr3)
#define KEY_PART4(k)        CORR_PART(k->corr4)
#define KEY_QC(k)           (k->qc)
#define KEY_RDBDAY(k)       TIME_DAY(k->rdbtime)
#define KEY_RDBHOUR(k)      TIME_HOUR(k->rdbtime)
#define KEY_RDBMINUTE(k)    TIME_MINUTE(k->rdbtime)
#define KEY_RDBSECOND(k)    TIME_SECOND(k->rdbtime)
#define KEY_RECDAY(k)       TIME_DAY(k->rectime)
#define KEY_RECHOUR(k)      TIME_HOUR(k->rectime)
#define KEY_RECMINUTE(k)    TIME_MINUTE(k->rectime)
#define KEY_RECSECOND(k)    TIME_SECOND(k->rectime)

/* day 6 bits,hour 5 bits, min 6 sec 6  1 spare*/

#define TIME_DAY(a)     (unsigned long)((a[0] & 0xFC)>>2)
#define TIME_HOUR(a)    (unsigned long)(((a[0]&0x3)<<3)+((a[1]&0xE0)>>5))
#define TIME_MINUTE(a)  (unsigned long)(((a[1]&0x1F)<<1)+((a[2]&0x8)>>3))
#define TIME_SECOND(a)  (unsigned long)((a[2] & 0x7E)>>1)

#define CORR_CORR(a)        (unsigned long)((unsigned char)((unsigned char)a & (unsigned char)0xFC) >>  (unsigned char)2)
#define CORR_PART(a)        (unsigned long)((unsigned char)((unsigned char)a & (unsigned char)0x02) >>  (unsigned char)1)

#define IS_SATTELITE(k)     (KEY_TYPE(k)==2||KEY_TYPE(k)==3||KEY_TYPE(k)==12)

#define UNLAT(l) ((double)(l)/100000.  -90.)
#define UNLON(l) ((double)(l)/100000. -180.)

/* Definition of rdb key */

typedef struct
{
#ifdef LITTLE_END
    unsigned char     type;
    unsigned char     subtype;
    unsigned char     date_time[ 5 ];
    unsigned char     spare02[ 25 ];
#else
    unsigned int      type       :8;     /* 8   bits =  1  bytes   */
    unsigned int      subtype    :8;     /* 16  bits =  2  bytes   */
    unsigned int      year       :12;    /* 28                     */
    unsigned int      month      :4;     /* 32  bits =  4  bytes   */
    unsigned int      day        :6;     /* 38                     */
    unsigned int      hour       :5;     /* 43                     */
    unsigned int      minute     :6;     /* 49                     */
    unsigned int      second     :6;     /* 55                     */
    unsigned int      spare01    :1;     /* 56  bits =  7   bytes  */
    char              spare02    [25];   /* 256 bits = 32   bytes  */
#endif
} keyheader;

typedef unsigned char timec[3];
typedef unsigned char correction;


typedef struct
{
#ifdef LITTLE_END
    keyheader        header;
    unsigned char    length[ 2 ];
    timec            rdbtime;
    timec            rectime;
    correction       corr1;
    correction       corr2;
    correction       corr3;
    correction       corr4;
    unsigned char    qc;
    unsigned char    spare09[ 3 ];
#else
    keyheader        header;
    unsigned int     length:16;
    timec            rdbtime;
    timec            rectime;
    correction       corr1;
    correction       corr2;
    correction       corr3;
    correction       corr4;
    unsigned int     qc          :8;
    unsigned int     spare09     :24;   /* 48 bytes */
#endif
} packed_key;

#define SEC1_LENGTH(a)  (getbits((unsigned char*)a,0,24))
#define SEC1_FLAGS(a, version)   (version>=4?getbits((unsigned char*)a,72,8):getbits((unsigned char*)a,56,8))

#ifdef LITTLE_END
#define SEC1_TYPE(s1)         ((unsigned int)s1.packed_section_1_data[8])
#define SEC1_SUBTYPE(s1)      ((unsigned int)s1.packed_section_1_data[9])
#define SEC1_YEAR(s1)         ((unsigned int)s1.packed_section_1_data[12])
#define SEC1_MONTH(s1)        ((unsigned int)s1.packed_section_1_data[13])
#define SEC1_DAY(s1)          ((unsigned int)s1.packed_section_1_data[14])
#define SEC1_HOUR(s1)         ((unsigned int)s1.packed_section_1_data[15])
#define SEC1_MINUTE(s1)       ((unsigned int)s1.packed_section_1_data[16])
#else
#define SEC1_TYPE(s1)         (s1.type)
#define SEC1_SUBTYPE(s1)      (s1.subtype)
#define SEC1_YEAR(s1)         (s1.year)
#define SEC1_MONTH(s1)        (s1.month)
#define SEC1_DAY(s1)          (s1.day)
#define SEC1_HOUR(s1)         (s1.hour)
#define SEC1_MINUTE(s1)       (s1.minute)
#endif

typedef struct
{
#ifdef LITTLE_END
        unsigned char    packed_section_1_data[32];
#else
	unsigned int	 length:24;			  /* length                 */  /* 3 -> 0-2   */
	unsigned int	 editon:8;			  /* edition number         */  /* 1 -> 3     */
	unsigned int     centre:16;           /* originating centre     */  /* 2 -> 4-5   */
	unsigned int	 seq:8;				  /* sequence number        */  /* 1 -> 6     */
	unsigned int	 key:8;				  /* presence of section 2  */  /* 1 -> 7     */
	unsigned int	 type:8;		  	  /* type of message        */  /* 1 -> 8     */
	unsigned int     subtype:8;			  /* subtype of message	    */  /* 1 -> 9     */
	unsigned int     table:16;            /* used WMO 94 table      */  /* 2 -> 10-11 */
	unsigned int     year:8;              /* year of century	    */  /* 1 -> 12    */
	unsigned int     month:8;			  /* month                  */  /* 1 -> 13    */
	unsigned int     day:8;               /* day                    */  /* 1 -> 14    */
	unsigned int     hour:8;              /* hour                   */  /* 1 -> 15    */
	unsigned int     minute:8;            /* minute                 */  /* 1 -> 16    */
	/* more after this .................. */
#endif
} packed_section_1;

/*=================================================================*/
/* Structure returned by bufrdc                                    */
/*=================================================================*/

typedef struct {
    fortint length;       /* 1 */
    fortint edition;      /* 2 */
    fortint center;       /* 3 */
    fortint update;       /* 4 */
    fortint flag;         /* 5 */
    fortint type;         /* 6 */
    fortint subtype;      /* 7 */
    fortint version;      /* 8 */
    fortint century;      /* 9 */
    fortint month;        /* 10 */
    fortint day;
    fortint hour;
    fortint minute;
    fortint table;
    fortint table_version;
    fortint junk[40];
} obssec1;

typedef struct {
    fortint sec2len;          /* 1 */
    fortint type;             /* 2 */
    fortint subtype;          /* 3 */
    fortint year;             /* 4 */
    fortint month;            /* 5 */
    fortint day;              /* 6 */
    fortint hour;             /* 7 */
    fortint minute;           /* 8 */
    fortint second;           /* 9 */
    fortint longitude1;       /* 10 */
    fortint latitude1;        /* 11 */
    fortint longitude2;       /* 12 */
    fortint latitude2;        /* 13 */
    fortint no_subsets;       /* 14 */
    fortint satellite_id;     /* 15 */
    fortint ident[9];         /* 16-24 */
    fortint length;           /* 25 */
    fortint junk[40];
} obskey;
