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

#ifndef Service_H
#define Service_H

//--#--define USE_THREADS

#ifdef USE_THREADS
#include <pthread.h>
#include "Queue.h"
#endif

class Service {

static Service *gHead;
static Service *gMonitor;

	Service *next_;

	int	    soc_;
	int     valid_;
	char    *name_;
	char    *host_;
	char    *user_;
	long    pid_;
	XDR     x_;

	long    ref_;
	int     ready_;

	time_t  timeout_;
	time_t  lastcall_;

	int     want_message_;
	int     want_progress_;

	int     alive_;

	int     outstanding_;
	int     maximum_;

#ifdef USE_THREADS

	pthread_t       thread_;
	pthread_mutex_t mutex_;
	pthread_cond_t  cond_;
	int             stop_;
	int             running_;
	int             threaded_;

	Queue           queue_;
	Queue           done_;

	void ThreadProc();
static void* StartThread(void*);
#endif


public:
	void SendRequest(request*);
	void CallService(request*);
	void GotReply(request*);

	 void HandleReply    (request *r);
	 void HandleProgress (request *r);
	 void HandleExit     (request *r);
	 void HandleService  (request *r);
	 void HandleFollowup (request *r);
	 void HandleMessage  (request *r);
	 void HandleRegister (request *r);
	 void HandleGetInfo  (request *r);
	 void HandleStart    (request *r);
	 void HandleWant     (request *r);
	 void HandleDrop     (request *r);
	 void HandleTimeout  (request *r);
	 void HandleAlive    (request *r);
	 void HandleMonitor  (request *r);
	 void HandleMaximum  (request *r);
	 void HandleLater    (request *r);
	 void HandleStop     (request *r);
	 void Dispatch       (request *r);

	Service(int);
	~Service();

static Service *Find(long);
static Service *Find(const char*);
static void     DispatchInput(fd_set&);
static void     StartService(const char*);
static void     ReplyFail(const char*,const char*,request*);
static void     UserMessage(const char *,...);
static void     Broadcast(request*);
static void     BroadcastMessage(request*);
static int      CheckTimeout();

	void NotifyMonitor(const char*,request*);
static void NotifyMonitor(const char*,request*,long,const char*);

	void ProcessIncoming();
#ifdef USE_THREADS
	int EncodeRequest(QElem*);
#else
	int EncodeRequest(request*);
#endif


	const char *Name()    { return name_;  }
	int   Busy();
};

#endif
