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

#define VALIDATE   0x01
#define STATISTICS 0x02
#define SCHEDULE   0x04
/* MARSLITE defines those verbs which can be executed when the client is running on behalf of a marslite client */
#define MARSLITE   0x08


static handler handlers[] = {
	{"RETRIEVE",handle_retrieve, VALIDATE | STATISTICS | SCHEDULE | MARSLITE, },
	{"WRITE",   handle_write,    0,},
	{"READ",    handle_read,     0,},
	{"COMPUTE", handle_compute,  0,},
	{"ARCHIVE", handle_archive,  VALIDATE | STATISTICS,},
#ifdef ECMWF
	{"REMOVE",  handle_remove, VALIDATE | STATISTICS,},
#endif

	{"DEFAULT", handle_default,  0,},

    /* On new DHS */

	{"ERASE",   handle_retrieve,   VALIDATE | STATISTICS,},
	{"FLUSH",   handle_control, VALIDATE | STATISTICS,},
	{"ATTACH",  handle_control, VALIDATE | STATISTICS,},
	{"LIST",    handle_control, MARSLITE, },
	{"BROWSE",  handle_control, VALIDATE,},
	{"STAGE",   handle_control, VALIDATE | STATISTICS | MARSLITE,},

	{"GET",     handle_control, 0,},

	{"STORE",   handle_control, VALIDATE | STATISTICS,},
	{"FETCH",   handle_retrieve, VALIDATE | STATISTICS,},

	{"END",     handle_end,     0,},
};


err handle_request(request *r,void *data)
{
	int i;
	char buf[80];
	static int n = 0;

	if(!r)
	{
		marslog(LOG_EROR,"Cannot handle null requests");
		return -2;
	}

	if(mars.verbose)
	{

		putchar('\n');
		marslog(LOG_INFO,"Processing request %d",++n);
	}

    if( add_hidden_parameters(r) != NOERR ) {
        marslog(LOG_EROR,"Error while processing hidden parameters");
        return -2;
    }

	if(mars.marslite_mode)
	{
        if(!mars.keep_database)
		{
            unset_value(r,"DATABASE");
		}
        unset_value(r,"FIELDSET");
	}

	if(mars.verbose)
	{
		putchar('\n');
		print_one_request(r);
	}


	for(i=0;i<NUMBER(handlers);i++)
		if(EQ(handlers[i].name,r->name))
		{
			err e;
			err ret;
			request *env    = get_environ();
			clock_t cpu     = 0;
			double  elapsed = 0;
			boolean    logstat = handlers[i].flags & STATISTICS;

			if(logstat) 
			{
				init_statistics(r,env);
				log_statistics("reqno","%d",n);
			}

			if( (handlers[i].flags & VALIDATE) == 0)
				mars.request_id = -1;
			else
				if((e = validate_request(r,env,mars.validate)) != 0)
				{
					if(logstat)
					{
						log_statistics("status","restricted");
						log_errors();
						flush_statistics(r,env);
					}
					return e;
				}

#if defined(ECMWF) && !defined(NOSCHEDULE)
			if((handlers[i].flags & SCHEDULE))
			{
				if((e = check_dissemination_schedule(r,env,logstat)) != 0)
				{
					/* Fail if dissemination schedule */
					if(mars.dissemination_schedule & SCHEDULE_FAIL)
					{
						if(logstat)
						{
							log_statistics("status","before_schedule");
							flush_statistics(r,env);
							log_errors();
						}
						return e;
					}
				}
			}
#endif

			if(!(handlers[i].flags & MARSLITE) && mars.marslite_mode)
			{
				int j = 0;
				marslog(LOG_WARN,"MARS running on behalf of marslite client");
				marslog(LOG_EROR,"Verb: %s disabled",handlers[i].name);
				marslog(LOG_WARN,"Allowed verbs in this mode:");
				for(j=0; j<NUMBER(handlers);j++)
				{
					if(handlers[j].flags & MARSLITE)
						marslog(LOG_WARN,"   %s",handlers[j].name);
				}
				log_statistics("status","marslite");
				return -1;
			}


			qenter(r);
			start_timer(); 
			e = handlers[i].proc(r,data);
			elapsed = stop_timer(buf);
			cpu     = timer_cpu();
			if(*buf) marslog(LOG_INFO,"Request time: %s",buf);
			qleave();

			print_all_timers();
			reset_all_timers();

			if((ret = fflush(stdout)) != 0)
				marslog(LOG_WARN,"Error while flushing output (%d)",ret);

			if(logstat)
			{
				log_statistics("cpu","%ld",(long)cpu);
				log_statistics("elapsed","%ld",(long)elapsed);
				log_statistics("status","%s",e==NOERR?"ok":"fail");
				if(e) log_errors();
				flush_statistics(r,env);
			}


			return e;
		}

	marslog(LOG_EROR,"No handler for verb '%s' found",r->name);
	return -1;
}

err handle_end(request *r,void *data)
{
	marslog(LOG_INFO,"Note: in this version of MARS, END is not compulsary");
	marslog(LOG_INFO,"Any remaining requests ignored");
	return END_REQUEST;
}
