/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

//
// .NAME:
//  BufrDecoder
//
// .AUTHOR:
//  Geir Austad
//
// .SUMMARY:
//  A concrete  class for decoding BUFR files
//  (uses Vesa's C++ classes to wrap the emoslib
//  routines).
//
// .CLIENTS:
//
//
// .RESPONSIBILITIES:
//  For each file, loop thru the messages and
//  return the messages matching the given criteria.
//
// .COLLABORATORS:
//  ECMWF's BUFR classes.
//
// .BASE CLASS:
//  Decoder
//
// .DERIVED CLASSES:
//
//
// .REFERENCES:
//
//  The design of this class is based on the "Factory" pattern
//  ("Design Patterns", page. 107).
//
//
#ifndef BufrDecoder_H
#define BufrDecoder_H 

#include <mars.h>
#include "libMetview/MvObs.h"
#include "MvDecoder.h"

// Until something more clever, set grouping period to 6 hours.
const int GROUPINGPERIOD = 6;

// Helper class used for grouping the observations into separate
// files. The files are then matched to subpages.
class GroupInfo
{
public:
	GroupInfo() : out_(0),path_("") {}

	GroupInfo(const string & path,bool writeData) : out_(0), path_(path)
	{ if ( writeData ) out_ = new MvObsSet(path_.c_str(),"w"); }

	~GroupInfo() { this->close(); }

	void write(MvObs &obs) { if ( out_ ) out_->write(obs); }

	void close() { if ( out_ ) { out_->close(); delete out_; out_ = 0; } }

	void deleteFile() { this->close(); unlink(path_.c_str()); }
	const string & path() { return path_; }

private:
	MvObsSet *out_;
	string path_;
};

typedef map<string, GroupInfo*, less<string> > GroupInfoMap;
typedef GroupInfoMap::iterator GroupInfoIterator;

class BufrDecoder: public Decoder {
public:

	// Contructors
	BufrDecoder ( const MvRequest& inRequest );

	// Destructor
	virtual ~BufrDecoder();

	// Overridden methods from Decoder class
	virtual bool ReadNextData ();

	virtual MatchingInfo CreateMatchingInfo ();

private:
	void groupInfo(MvObsSetIterator &);
	void findTime(TDynamicTime&,string&);
	void generateGroupFileName(string &, const string &);
	void cleanMap();

	// No copy allowed
	BufrDecoder(const BufrDecoder&);
	BufrDecoder& operator=(const BufrDecoder&){return *this;}

	// Members
	GroupInfoMap groupInfo_;
	GroupInfoIterator groupIterator_;
	string path_;
};

//____________________________________________________

class ObsGroupControl
{
public:
	ObsGroupControl(){}

	static string groupTimeString( const TDynamicTime& tim );
	static void printGroupingLimits( const string &groupTimeString );
	static int groupPeriod();
	static int groupPeriodStartMinute();
	static bool useObsTime()
		{ return useObsTime_; }

	static void   groupingValues();
	static void   setGroupingPeriod( int hours );
	static void   setGroupingPeriodStart( int minutes );
	static void   setUseObsTime( bool useObsTime )
		{ useObsTime_ = useObsTime; }

private:
	static int    groupPeriodHours_;
	static int    groupPeriodStartMinute_;
	static bool   useObsTime_;
	static bool   firstTime_;
};
#endif
