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

#include <math.h>
#include <limits.h>
#include "mars.h"

/*
 LLMATRIX
 AREA
 GRID
 NORTH
 WEST
 EAST
 SOUTH
 NLAT
 NLON
 DATA
*/


err llmatrix_to_grib(const char *in,const char *out)
{
	fortint     ksec0[ISECTION_0];
	gribsec1    ksec1;
	gribsec2_ll ksec2;
	fortint     ksec3[ISECTION_3];
	fortint     ksec4[ISECTION_4];

	fortfloat   psec2[RSECTION_2];
	fortfloat   psec3[RSECTION_3];
	fortfloat   missing = FLT_MAX;


	err e = 0;
	int miss = 0;
	fortint nlat,nlon,nbits;
	fortfloat north,west,south,east,ew,ns;
	char *buffer =NULL;
	fortint buflen;
	fortfloat *psec4 =NULL;
	fortint i,npoints;
	int n = 0;
	char line[1024];
	char *tmp = marstmp();
	FILE *f,*g;
	request *r;
	const char *p;

	CLEAR(ksec0);
	CLEAR(ksec1);
	CLEAR(ksec2);
	CLEAR(ksec3);
	CLEAR(ksec4);
	CLEAR(psec2);
	CLEAR(psec3);

	f = fopen(in,"r");
	if(!f)
	{
		marslog(LOG_EROR|LOG_PERR,"Cannot open %s",in);
		return -1;
	}

	g = fopen(tmp,"w");
	if(!g)
	{
		marslog(LOG_EROR|LOG_PERR,"Cannot open %s",tmp);
		fclose(f);
		return -1;
	}


	while(fgets(line,sizeof(line),f))
	{
		if(*line != '#')
		{
			int l = strlen(line)-1;

			while(l >= 0 && (
					line[l] == ' '  || 
					line[l] == '\n' || 
					line[l] == ','  || 
					line[l] == '\t')
					)
				line[l--] = 0;


			if(n == 0) {
				/* Look for a = */
				char *p  = line;
				int flg  = 0;
				while(*p) if(*p++ == '=') flg++;
				/* If a =, add a verb */
				if(flg) {
					fprintf(g,"LLMATRIX");
					fprintf(g,",%s",line);
				}
				else fprintf(g,"%s",line);
			}
			else fprintf(g,",%s",line);
			n++;
		}
		if(strncmp(line,"#DATA",5)==0) 
			break;
	}

	fclose(g);

	r = read_request_file(tmp);
	unlink(tmp);
	print_all_requests(r);

	north   = atof((p=get_value(r,"NORTH",0))?p:"0");
	west    = atof((p=get_value(r,"WEST", 0))?p:"0");
	ew      = atof((p=get_value(r,"GRID", 0))?p:"0");
	ns      = atof((p=get_value(r,"GRID", 1))?p:"0");
	nlat    = atol((p=get_value(r,"NLAT", 0))?p:"0");
	nlon    = atol((p=get_value(r,"NLON", 0))?p:"0");
	missing = (p=get_value(r,"MISSING", 0))?atof(p):missing;

	if(ew == 0 || ns == 0 || nlat == 0 || nlon == 0)
	{
		marslog(LOG_EROR,"Invalid ll-matrix");
		fclose(f);
		return -1;
	}

	npoints = nlat * nlon;

	south   = north - (nlat-1) * ns;
	east    = west  + (nlon-1) * ew;

	/* ============================================================ */

	psec4 = NEW_ARRAY(fortfloat,npoints);

	n = 0;
	for(i=0;i<npoints;i++)
	{
#ifndef R64
		if(fscanf(f,"%f",&psec4[i])>0)
#else
		if(fscanf(f,"%lf",&psec4[i])>0)
#endif
		{
			n++;
			if(psec4[i] == missing)
				miss++;
		}
	}
	fclose(f);

	if(n != npoints)
	{
		marslog(LOG_EROR,"File %s, read %d values out of %d expected",
			in,n,npoints);
		e = -1;
		goto error;
	}

	 /* 1 k header + 32 bit packing */

	buflen = (npoints + 1024)*4;
	buffer = (char*)MALLOC(buflen);

	/* ============================================================ */

	ksec1.version         = 128;
	ksec1.center          =  98;
	ksec1.generation      = mars.computeflg;
	ksec1.grid_definition = 255;
	ksec1.flags           = miss?192:128;


	ksec1.parameter       = 255;
	ksec1.level_type      = GRIB_SURFACE;

	ksec1.year            = 94;
	ksec1.month           = 1;
	ksec1.day             = 1;
	ksec1.century         = 20;


	ksec1.time_unit       = 1;
	ksec1.local_use       = 1;
	ksec1.local.ecmwf_local_id  = GRIB_ENSEMBLE_FORECAST;
	ksec1.local.mars_class      = GRIB_CLASS_OD;
	ksec1.local.mars_type       = 3;    /* IA */
	ksec1.local.mars_stream     = 1025; /* DA */
	ksec1.local.mars_expver     = 0x30303031; /* 01 */

	ksec2.data_rep        = GRIB_LAT_LONG;
	ksec2.points_parallel = nlon;
	ksec2.points_meridian = nlat;

	ksec2.limit_north = (fortint)(north * GRIB_FACTOR);
	ksec2.limit_west  = (fortint)(west * GRIB_FACTOR);
	ksec2.resolution  = 128;
	ksec2.limit_south = (fortint)(south * GRIB_FACTOR);
	ksec2.limit_east  = (fortint)(east * GRIB_FACTOR);
	ksec2.grid_ew     = (fortint)(ew * GRIB_FACTOR);
	ksec2.grid_ns     = (fortint)(ns * GRIB_FACTOR);


	/*  Missing value */

	ksec3[0] = 0;
	ksec3[1] = INT_MAX;
	psec3[1] = missing;

	/*  Data */

	ksec4[0] = npoints;
	ksec4[1] = nbits = best_packing(ksec4[1]);

	printf("nbits   = %d\n",nbits);
	printf("missing = %g\n",missing);

	if(cgribex( ksec0,(fortint*)&ksec1, (fortint*)&ksec2,psec2,
		ksec3,psec3, ksec4,psec4,
		npoints, buffer, &buflen, "C") != 0)
	{
		marslog(LOG_EROR,"Error encoding GRIB");
		e = -1;
		goto error;
	}

/*
	psec3[1] = 9999;
	e = cgribex( ksec0,(fortint*)&ksec1, (fortint*)&ksec2,psec2,
		ksec3,psec3, ksec4,psec4,
		npoints, buffer, &buflen, "D");
	printf("decode %d\n",e);
*/

	f = fopen(out,"w");
	if(!f)
	{
		marslog(LOG_EROR|LOG_PERR,"Cannot open %s",out);
		e = -1;
		goto error;
	}

	if(fwrite(buffer,1,buflen,f) != buflen)
	{
		marslog(LOG_EROR|LOG_PERR,"fwrite(%s) failed",out);
		e = -1;
	}
		
	if(fclose(f))
	{
		marslog(LOG_EROR|LOG_PERR,"fclose(%s) failed",out);
		e = -1;
	}

error:
	FREE(psec4);
	FREE(buffer);
	return e;
}


err grib_to_llmatrix(const char *g,const char *m)
{
	return -1;
}
