/*
 * © 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.
 */

// File ObsKey.h
// Manuel Fuentes - ECMWF Oct 96

#ifndef ObsKey_H
#define ObsKey_H

#include "fortint.h"
#include <memory.h>


#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <iomanip>

using namespace std;

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

} key; /* 48 bytes */

typedef long Ordinal;

// Forward declarations

class BadBufr {

public:
	BadBufr(const string& s): s_(s) {}
	const string& text() { return s_; }

private:
	string s_;
};

class ObsKey {
public:

// -- Exceptions
	// None

// -- Contructors

	ObsKey() {}
	ObsKey(char*,fortint,bool=true);

// -- Destructor
	~ObsKey() {}

// -- Operators

	bool operator<(const ObsKey& other) const
		{  return ::memcmp(&key_,&other.key_,sizeof(keyheader)) < 0; ; }
	bool operator==(const ObsKey& other) const
		{  return ::memcmp(&key_,&other.key_,sizeof(keyheader)) == 0; ; }

// -- Methods

	Ordinal     length()   const;
	Ordinal		type()	   const { return key_.header.type; }
	Ordinal		subtype()  const { return key_.header.subtype; }

	double latitude() const;
	double longitude() const;

    int   year()     const;
    int   month()    const;
    int   day()      const;
    int   hour()     const;
    int   minute()   const;
    int   second()   const;
	long  station()  const;

    void print(ostream&) const; // Change to virtual if base class


private:

// -- Members

	key			key_;
	Ordinal     length_;

// -- Overridden methods
	// None

// -- Class members
	// None

// -- Class methods
	// None

// -- Friends

    friend ostream& operator<<(ostream& s,const ObsKey& p)
        { p.print(s); return s; }

};

#endif
