/*
 * © 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 "mars.h"
#if defined(hpux)
#define EMPRESS
#endif

#ifdef EMPRESS
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <ctype.h>


/* db prototypes */

static void    rdb_init(void);
static err     rdb_open(void *data, request *r, request *e, int mode);
static err     rdb_close(void *data);
static err     rdb_read(void *data, request *r, void *buffer, long *length);
static err     rdb_write(void *data, request *r, void *buffer, long *length);
static err     rdb_query(void *data, request *r, long *length);
static boolean rdb_check(void *data, request *r);


extern err setvalrdb(const char* name, const char* val);
extern err setrangerdb(const char* name, const char* val1, const char* val2);
extern err readrdb(void* data, long* length);
extern err openrdb(const char *);
extern err closerdb(void);

static base_class _rdb_base = {

	NULL,                   /* parent class */
	"rdb_base",             /* name         */

	false,                  /* inited       */

	NULL,

	NULL,
	NULL,

	rdb_init,               /* init         */

	rdb_open,               /* open         */
	rdb_close,              /* close        */

	rdb_read,               /* read         */
	rdb_write,              /* write        */

	NULL,                   /* control      */

	rdb_check,				/* check */

};



/* the only 'public' variable ... */

base_class *rdb_base = &_rdb_base;


static void rdb_init(void)
{
	marslog(LOG_DBUG,"rdb_init:Initialize RDB");
}


static err rdb_open(void *data, request *r, request *e, int mode)
{
    parameter *p = 0;
    request   *t = empty_request(0);
	long      flags  = expand_flags(EXPAND_MARS| EXPAND_SUB_LISTS);
	request   *s = 0;
	const char *type = 0;

	unset_value(r,"TARGET");
	s = expand_all_requests(mars_language(),mars_rules(),r);
	type = get_value(s,"TYPE",0);

	expand_flags(flags);
	reset_language(mars_language());

	marslog(LOG_DBUG,"rdb_open");
	if(type && !EQ("OB",type))
	{
		free_all_requests(s);
		return NOERR;
	}

	/* Open the database */
	openrdb(NULL);

	if(mars.debug)
		print_all_requests(s);

    names_loop(s,sort_request,&t);

    p = s->params;
    while(p)
    {
        if(get_value(t,p->name,0) == 0)
            valcpy(t,s,p->name,p->name);

        p = p->next;
    }

	p = t->params;

	while(p)
    {
        marslog(LOG_DBUG,"setvalrdb: %s %s",p->name,p->values->name);
		
		if(p->count > 1 && EQ(p->name,"TIME"))
		{
			const char *q1 = 0;
			const char *q2 = 0;
			if(EQ("TO",get_value(s,p->name,1)))
			{
				q1 = get_value(s,p->name,0);
				q2 = get_value(s,p->name,2);
				setrangerdb(p->name,q1,q2);
			}
			else 
			{
				int i = 0;
				while(q1 = get_value(s,p->name,i++))
					setvalrdb(p->name,q1);
			}
			

		} else {
			const char *q = 0;
			int i = 0;
			while(q = get_value(t,p->name,i++))
				setvalrdb(p->name,q);
		}

        p = p->next;
	}

	free_all_requests(t);
	free_all_requests(s);

	return NOERR;
}


static err rdb_close(void *data)
{
	marslog(LOG_DBUG,"rdb_close");
	
	return closerdb();
}



static err rdb_read(void *data,request *r,void *buffer,long *length)
{
	static int count = 0;
	long size = *length;
	err e = NOERR;
	boolean save = (getenv("SAVE_DATA_READRDB") != NULL);


	marslog(LOG_DBUG,"-> rdb_read: %ld bytes",*length);

	e = readrdb(buffer,length);
	marslog(LOG_DBUG,"<- rdb_read: %ld bytes",*length);
	if(*length > size)
		marslog(LOG_EROR,"Read %ld bytes > buffer size (%ld bytes)",*length,size);

	if(save)
	{
		FILE   *fd;
		char fname[50];
		sprintf(fname,"readrdb.buffer.%d",count);
		if( (fd = fopen(fname,"w")) == NULL)
			marslog(LOG_EROR|LOG_PERR,"Error saving buffer read from RDB. Can't open file %s",fname);
		else
		{
			if(fwrite(buffer,1,*length,fd) != *length)
				marslog(LOG_EROR|LOG_PERR,"Error writing to file %s",fname);
		}
		fclose(fd);
	}
	
	count++;
	if(e != NOERR)
		return EOF;

	return e;
}


static err rdb_write(void *data, request *r, void *buffer, long *length)
{
	marslog(LOG_DBUG,"rdb_write:Not implemented");

	return NOERR;
}


static boolean rdb_check(void  *data, request *r)
{
	const char *type = get_value(r,"TYPE",0);

	marslog(LOG_DBUG,"rdb_check: ");
	if(EQ(type,"OB"))
		return true;

	return false;
}

#else
#include "mars.h"
extern base_class _nullbase;
base_class *rdb_base = &_nullbase;
#endif
