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

#ifndef GribMetaData_H
#define GribMetaData_H

#include <iostream>
#include <list>
#include <map>
#include <vector>

#include "MvMessageMetaData.h"

//for off_t
#include "mars.h"

class MvKeyProfile;

using namespace std;

class GribItem
{
public: 
	void pos(string s) {pos_=s;};
	string pos() {return pos_;};
	void name(string s) {name_=s;};
	string name() {return name_;};	
	void type(string s) {type_=s;};
	string type() {return type_;};	
	void value(string s) {value_=s;};
	string value() {return value_;};
	void intValue(string s) {intValue_=s;};
	string intValue() {return intValue_;};
	void description(string s) {description_=s;};
	string description() {return description_;};
	void addAlias(string s) {alias_.push_back(s);};
	const vector<string>& alias() {return alias_;};
	void addArrayData(string s) {array_.push_back(s);};
	const vector<string>& arrayData() {return array_;};	

protected:
	string pos_;
	string name_;
	string type_;
	string value_;
	string intValue_;
	string description_;
	vector<string> alias_;
	vector<string> array_;
	
};

class GribSection;
typedef list<GribSection*>::const_iterator GribSectionIterator;

class GribSection
{
public:
	GribSection() {};
	~GribSection();
	void name(string s) {name_=s;};
	string name() {return name_;};	
	void lenght(int i) {lenght_=i;};
	int lenght() {return lenght_;};
	void offset(int i) {offset_=i;};
	int offset() {return offset_;};
	void addItem(GribItem* i) {item_.push_back(i);};
	int itemNum() {return item_.size();}
	const vector<GribItem*> & item() {return item_;};

protected:
	string name_;
	int lenght_;
	int offset_;
	vector<GribItem*> item_;
};


class GribWmoDump
{
public:
	GribWmoDump(string &tmpfilename) {tmpfilename_ = tmpfilename;};
	~GribWmoDump();
	void clear();
	void read(const string&, int);
	int  sectionNum() const {return section_.size();} 
	const string& text() const {return text_;} 
	const vector<GribSection*>& section() {return section_;}

protected:
	vector<GribSection*> section_;
	string     text_; 
	string     tmpfilename_;
};

class GribStdDump
{
public:
	GribStdDump(string &tmpfilename) {tmpfilename_ = tmpfilename;};
	~GribStdDump();
	void clear();
	void read(const string&, int);
	int  itemNum() const {return item_.size();} 
	const string& text() const {return text_;} 
	const vector<GribItem*>& item() {return item_;};

protected:
	vector<GribItem*> item_;
	string     text_; 
	string     tmpfilename_;
};

class GribMvDump
{
public:
	GribMvDump(string &tmpfilename);
	~GribMvDump();
	void clear();
	void read(const string&, int);
	int  itemNum() const {return item_.size();} 
	const vector<GribItem*>& item() {return item_;};

protected:
	vector<GribItem*> item_;
	string     tmpfilename_;
	static map<int,string> keyMap_;
};

class GribValueDump
{
public:
	GribValueDump();
	~GribValueDump();
	void clear();
	void read(const string&, int);
	double* latitude() {return latitude_;}
	double* longitude() {return longitude_;}
	double* value() {return value_;}
	int num() {return num_;}
	int decimalPlaces() {return decimalPlaces_;}
	double average() {return average_;}
	double stdev() {return stdev_;}
	double skewness() {return skewness_;}
	double kurtosis() {return kurtosis_;}

protected:
	void readFailed(FILE*,grib_handle*);
	
	double* latitude_;
	double* longitude_;
	double* value_;
	int num_;
	int decimalPlaces_;
	string gridType_;
	double average_;
	double stdev_;
	double skewness_;
	double kurtosis_;
	
};


class GribMetaData : public MvMessageMetaData
{ 
public: 
	GribMetaData();
	~GribMetaData();
	void setFileName(string);
	int getGribCount();
	void getKeyList(int,string,MvKeyProfile *);
	void getKeyList(int,string,list<string> &);
	void loadKeyProfile(MvKeyProfile *);
	int getEstimatedMessageNum();
	long gribapiVersionNumber();
	void setFilter(vector<off_t>,vector<int>);
	bool hasMultiMessage() {return hasMultiMessage_;}
	
private:			
	void readMessages(MvKeyProfile *);	
	void readMessage(MvKeyProfile*,grib_handle *);
	void setDateStructure();
	int computeTotalMessageNum();
	bool hasMultiMessage_;

};

#endif
