/*
 * © 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)
#define KEY_RESTRICTED(k) RETRICTED_BIT(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 RETRICTED_BIT(a) (unsigned long)((a[2] & 0x1))

#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;
