/*
 * © 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 <stdio.h>
#include <grib_api.h>
#include <ctype.h>

#include "mars.h"


static void upper_case(char *p)
{
	while(*p)
	{
		if(islower(*p)) *p = toupper(*p);
		p++;
	}

}

err handle_to_request (request *r, grib_handle* g, mars_field_index* idx )
{
	grib_keys_iterator* ks;
	char name[80];
	char value[80];
	size_t len = sizeof(value);
	long local;
	int e;
	const char *p;
	const char *stream = get_value(r,"STREAM",0);
	const char *number = get_value(r,"NUMBER",0);

	if(!g) return -1;


	/* printf("------------\n"); */
	ks  = grib_keys_iterator_new(g,GRIB_KEYS_ITERATOR_ALL_KEYS,"mars");

	while(grib_keys_iterator_next(ks))
	{

		strcpy(name,grib_keys_iterator_get_name(ks));

		if((e = grib_keys_iterator_get_string(ks,value,&len)) != 0)
			marslog(LOG_EROR,"Cannot get %s as string %d (%s)",name,e,
					grib_get_error_message(e));

		/* printf("MARS -> %s ... %s\n",name,c); */

		if(idx)
		{
			double d;
			long l;
			boolean d_ok, l_ok;

        	len = 1;
        	d_ok = (grib_keys_iterator_get_double(ks,&d,&len) == 0);

	        len = 1;
    	    l_ok = (grib_keys_iterator_get_long(ks,&l,&len) == 0);

			mars_field_index_add(idx, name, 1, value, l_ok, l, d_ok, d);
		}

		upper_case(name);

		if(!EQ(name,"EXPVER"))
			upper_case(value);


		set_value(r,name,"%s",value);
		len = sizeof(value);
	}

	strcpy(name,"identifier");
	len = sizeof(value);
	if((e = grib_get_string(g,name,value,&len)) != 0)
	{
		marslog(LOG_EXIT,"Cannot get %s as string %d (%s)",name,e,
				grib_get_error_message(e));
		mars.pseudogrib =  0;
	}
	else
	{
		if(strcmp(value,"HDF5") == 0) {
			// marslog(LOG_INFO,"Message is NetCDF");
		}
		else
		{
			mars.pseudogrib = (strcmp(value,"BUDG") == 0) || (strcmp(value,"TIDE") == 0);
			if(mars.pseudogrib)
			{
				marslog(LOG_WARN,"Pseudo GRIB encountered (%s)",value);
				if(stream == NULL)
					stream = getenv("MARS_PSEUDOGRIB_STREAM");

				if(stream != NULL)
				{
					marslog(LOG_DBUG,"Setting STREAM to '%s'",stream);
					set_value(r,"STREAM","%s",stream);
				}

				if(number != NULL)
				{
					marslog(LOG_DBUG,"Setting NUMBER to '%s'",number);
					set_value(r,"NUMBER","%s",number);
				}
			}
			else {
				if(strcmp(value,"GRIB") != 0)
					marslog(LOG_EXIT,"Unexpected message type (%s)",value);
				else
				{
					/* Get the edition */
					long edition = 0;
					if((e = grib_get_long(g,"edition",&edition)) != 0)
					{
						marslog(LOG_EXIT,"Cannot get edition as long: %d (%s)",e,
								grib_get_error_message(e));
					}
					set_value(r,"_EDITION","%ld",edition);
				}
			}
		}
	}

	if(grib_get_long(g,"localDefinitionNumber",&local) ==  0 && local == 191) /* TODO: Not grib2 compatible, but speed-up process */
	if(grib_get_size(g,"freeFormData",&len) ==  0 && len != 0)
	{
		char buffer[10240];
		len = sizeof(buffer);
		if((e = grib_get_bytes(g,"freeFormData",buffer,&len)) != 0)
			marslog(LOG_EROR,"Cannot get freeFormData %d (%s)",name,e,
					grib_get_error_message(e));
		else {
			request* s = decode_free_format_request(buffer,len);

			if(mars.debug)
			{
				marslog(LOG_DBUG,"Free format request:");
				print_all_requests(s);
			}
			/* set_value(r,"PARAM","%d.%d",s1->parameter,s1->version); */

			reset_language(mars_language());
			mars.expflags = EXPAND_MARS | EXPAND_NO_DEFAULT;
			s = expand_mars_request(s);
			if( s == NULL)
			{
				/* if(mars.exit_on_failed_expand) */
				{
					e = -2;
					marslog(LOG_EROR,"Failed to expand request");
				}
			}
			mars.expflags = EXPAND_MARS;
			reqcpy(r,s);
			free_all_requests(s);

		}

	}

	grib_keys_iterator_delete(ks);
	return e;
}

err grib_to_request_index (request *r, char *buffer, long length, mars_field_index* idx )
{
	err e;
	grib_handle *g = grib_handle_new_from_message(0,buffer,length);
	e = handle_to_request(r,g,idx);
	grib_handle_delete(g);
	return e;
}

err grib_to_request (request *r, char *buffer, long length)
{
	return grib_to_request_index(r,buffer,length,NULL);
}



