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

#include <Metview.h>
#include <MvTimeSerie.h>
#include <Cached.h>



class Metgram : public MvService {
protected:
	Metgram(char* a) : MvService(a)			{};
	void   grib(MvRequest&,MvRequest&);
	void   bufr(MvRequest&,MvRequest&);
	void   do_one(MvRequest&, MvRequest&, MvTimeSerie&);
public:
	Metgram() : MvService("METGRAM") 		{};
	void serve(MvRequest&,MvRequest&);
};

static Cached GRIB("GRIB");
static Cached BUFR("BUFR");

void Metgram::serve(MvRequest& in,MvRequest& out)
{

	MvRequest data;


	in.getValue(data,"DATA"); 

	Cached type(data.getVerb());

	if ( type == GRIB )
	  grib(in, out);
	else if ( type == BUFR)
	  bufr(in, out);
	else
	  setError( 1, "Service Metgram unable to work on data of type %s"
		  , (const char*)type );

	out.print();
}

	
void Metgram::grib(MvRequest& in,MvRequest& out)
{
	MvRequest grib         =  in("DATA");
	MvRequest station      =  in("STATION");
	MvRequest axis         =  in("VERTICAL_AXIS");
	MvRequest graph        =  in("ATTRIBUTES");

	
	printf("----------------INPUT REQUEST-------------------------\n");
	in.print();
	printf("------------------------------------------------------\n");
	printf("------------------------------------------------------\n");

	
	MvTimeSerie serie(axis,graph);

//	while (grib) {
		do_one(grib, station, serie);
//		grib.advance();
//	}
	
	out = serie.getRequest();
		
	printf("----------------OUTPUT REQUEST------------------------\n");
	out.print();
	printf("------------------------------------------------------\n");
	printf("------------------------------------------------------\n");
}

void Metgram::do_one(MvRequest& grib, MvRequest& station, 
	MvTimeSerie& serie)
{
	char		ref[1024];
	char		legend[1024];
	int   		param = -1;
	int   		level = -1;
	int   		number = -1;
	int 		idat= -1 ,dateinc = 0,fdato= 0;
	double 		lat, lon;
	const char  		*name, *icon_name;
	MvRequest	last_station;
	

	MvFieldSet          fs(grib);
	MvFieldSetIterator  iter(fs);

//	iter.sort("DATE");
//	iter.sort("TIME");
	iter.sort("STEP"); 
	iter.sort("LEVELIST"); 
	iter.sort("NUMBER"); 
	iter.sort("PARAM"); 


	MvField field;
	while(field = iter())
	{
		MvFieldExpander expand(field);
		double min = field[0]; 
		double max = field[0]; 
		MvRequest r = field.getRequest();

		int       p = r("PARAM");
		
		int       l = r("LEVELIST");
		int       n = r("NUMBER");
		int idato = r("DATE");
		int itime = r("TIME");
		const char*  type = r("TYPE");

		double    x = r("STEP");
		printf(" %lf date %d\n",x,idato);
		if ( idat == -1 ) {
			idat = idato;
			fdato = idato;
		}
		if ( idat != idato ) {
			idat = idato;
			dateinc += 10000;
		}
		itime += dateinc;
		serie.setDate(fdato, itime);

		if (p != param || l != level || n != number) {
			param  = p;
			level  = l;
			number = n;
			while (station) {
				icon_name =  station("_CLASS");
		            	name      =  station("NAME");
				if (icon_name)
				  last_station = station;

				sprintf(ref, "%d/%s/%d/%d", param, name,level,number);
				lat = station("LATITUDE");
				lon = station("LONGITUDE");
				float abslat = lat > 0. ? lat : -lat;
				float abslon = lon > 0. ? lon : -lon;

				sprintf(legend, "%d/%s Level=%d, %4.1f%c %5.1f%c",
					param, name,level,
					abslat, abslat >= 0.059 ? (lat > 0. ? 'n' : 's') : ' ',
					abslon, abslon >= 0.059 ? (lon > 0. ? 'e' : 'w') : ' ');
				serie.createNewGroup(ref, legend);
				serie.addIconInfo(ref, "DATA", grib);
				serie.addIconInfo(ref, "STATION", last_station);

				if(level)
					serie.setTitle(ref, "Plot of %d level %d at %s", 
						p, l, name);
				else
					serie.setTitle(ref, "Plot of %d at %s", p, name);

				station.advance();
			}
			station.rewind();
		}
		
		while (station) { 
			double	BIGDOUBLE = 3.4E35;
			name      = station("NAME");
			lat       = station("LATITUDE");
			lon       = station("LONGITUDE");
			sprintf(ref, "%d/%s/%d/%d", p, name,level,number);
			double    y = field.interpolateAt(lon, lat);
			if ( y < BIGDOUBLE )
			  serie.addPoint(ref, x, y);

			station.advance();
		}
		station.rewind();

		
	}
}

void Metgram::bufr(MvRequest&, MvRequest&)
{
/*****************
	MvRequest bufr;
	
	in.getValue(bufr,"DATA"); 
	MvRequest station;
 	in.getValue(station,"STATION");
	double ident = station("IDENT");

	while (station) {
		char *name =  station("NAME");
		printf("station : %s\n", name);
		station.advance();
	}

 	in.getValue(station,"STATION");
	MvRequest magics;

	in.getValue(magics,"VISUALISATION");
	printf("Magics parameter\n");
	magics.print();


	boolean bar     = false;
	boolean scale 	= false;
	boolean overlay = false;
	Cached  BAR("BAR");
	Cached  YES("YES");

	if (magics("GRAPH_TYPE") == BAR) bar = true;
	if (in("SCALE") == YES) scale = true;
	if (in("OVERLAY_STATIONS") == YES) overlay = true;

	MvObsSet          obsset(bufr);
	MvObsSetIterator  iter(obsset);

	MvBufrParam tempe("T");
	iter.setWmoStation(ident); 

	MvObs obs;
	while(obs = iter())
	{
		obs.printParameters();
		float t = obs.value(tempe);
		printf("Tempe : %f\n", t);
	}
*****************************/
}

int main(int argc,char **argv)
{
	MvApplication theApp(argc,argv);
	Metgram     metgram;

	metgram.addModeService("STATION", "STATION");
	metgram.addModeService("GRIB", "DATA");
	metgram.addModeService("PAXIS", "VERTICAL_AXIS");

	theApp.run();
}
