//-----------------------------------------------------------------------------
// Copyright (c) 1994,1995 Southeastern Universities Research Association,
//                         Continuous Electron Beam Accelerator Facility
//
// This software was developed under a United States Government license
// described in the NOTICE file included as part of this distribution.
//
// Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606
//-----------------------------------------------------------------------------
//
// Description:
//      RSVC Server/Client Protocol Information and Data Information
//      This class contains protocol information related to callbacks
//      1. operation code
//      2. request   id
//      3. socket    id -->for server only
//      4. client    id
//      5. callback  id -->from client to server
//
//
// Author:  
//      Jie Chen
//      Jefferson Lab HPC Group
//
// Revision History:
//   $Log: rsvcEvent.java,v $
//   Revision 1.1.1.1  2000/05/23 15:12:50  pal
//   cdev_psi_1.7.2
//
//   Revision 1.1  1999/10/18 17:12:42  chen
//   *** empty log message ***
//
//
//
import java.io.*;
import rsvcConfig;
import rsvcData;
import rsvcEventHandler;

public final class rsvcEvent
{
    private int      opcode_;
    private int      cbkid_;
    private int      eventid_;
    private int      clientid_;
    private int      socketid_;
    private int      status_;
    private rsvcData data_;
    private rsvcEventHandler handler_ = null;

    /**
     * Construct an emtpy rsvcEvent object
     */
    public rsvcEvent () 
    {
	opcode_ = rsvcConfig.RSVC_OP_UNKNOWN;
	cbkid_ = 0;
	eventid_ = 0;
	clientid_ = 0;
	socketid_ = 0;
	status_ = rsvcConfig.RSVC_SUCCESS;
	data_ = new rsvcData ();
	handler_ = null;
    }

    /**
     * Construct a rsvcEvent Object with given parameters
     */
    public rsvcEvent (rsvcData data, int opcode, int cbkid)
		      
    {
	data_ = new rsvcData (data);
	opcode_ = opcode;
	cbkid_ = cbkid;
	eventid_ = 0;
	clientid_ = 0;
	socketid_ = 0;
	status_ = rsvcConfig.RSVC_SUCCESS;
	handler_ = null;
    }

    /**
     * Construct a rsvcEvent Object with given parameters
     */
    public rsvcEvent (rsvcData data, int opcode, int cbkid,
		      int eventid, int clientid, int socketid,
		      int status)
    {
	data_ = new rsvcData (data);
	opcode_ = opcode;
	cbkid_ = cbkid;
	eventid_ = eventid;
	clientid_ = clientid;
	socketid_ = socketid;
	status_ = status;
	handler_ = null;
    }


    /**
     * Construct a rsvcEvent Object without data object
     */
    public rsvcEvent (int opcode, int cbkid,
		      int eventid, int clientid, int socketid,
		      int status)
    {
	data_ = new rsvcData();
	opcode_ = opcode;
	cbkid_ = cbkid;
	eventid_ = eventid;
	clientid_ = clientid;
	socketid_ = socketid;
	status_ = status;
	handler_ = null;
    }


    /**
     * Construct a rsvcEvent Object with data object only
     */
    public rsvcEvent (rsvcData data)
    {
	data_ = new rsvcData(data);
	opcode_ = 0;
	cbkid_ = 0;
	eventid_ = 0;
	clientid_ = 0;
	socketid_ = 0;
	status_ = rsvcConfig.RSVC_SUCCESS;
	handler_ = null;
    }

    /**
     * Construct a rsvcEvent Object using an exising rsvcEvent
     */   
    public rsvcEvent (rsvcEvent event)
    {
	data_ = new rsvcData (event.data_);
	opcode_ = event.opcode_;
	cbkid_ = event.cbkid_;
	eventid_ = event.eventid_;
	clientid_ = event.clientid_;
	socketid_ = event.socketid_;
	status_ = event.status_;	
	handler_ = event.handler_;
    }

    /**
     * Check whether two events have the same signature
     */
    public boolean match (rsvcEvent event)
    {
	if (opcode_ == event.opcode_ &&
	    cbkid_ == event.cbkid_   &&
	    eventid_ == event.eventid_)
	    return true;
	return false;
    }

    /**
     * Set data and other paremeters
     */
    public void set (rsvcData data, 
		     int opcode,   int cbkid,
		     int eventid,    int clientid, 
		     int socketid, int status)
    {
	data_ = new rsvcData (data);
	opcode_ = opcode;
	cbkid_ = cbkid;
	eventid_ = eventid;
	clientid_ = clientid;
	socketid_ = socketid;
	status_ = status;
    }

    /**
     * Set data and other paremeters
     */
    public void set (int opcode,   int cbkid,
		     int eventid,    int clientid, 
		     int socketid, int status)
    {
	opcode_ = opcode;
	cbkid_ = cbkid;
	eventid_ = eventid;
	clientid_ = clientid;
	socketid_ = socketid;
	status_ = status;
    }

    /**
     * Clean up everything
     */ 
    public void cleanup ()
    {
	data_.remove ();
	cbkid_ = 0;
	eventid_ = 0;
	clientid_ = 0;
	socketid_ = 0;
	status_ = rsvcConfig.RSVC_SUCCESS;
	handler_ = null;
    }

    /**
     * Get Opcode of this event
     */
    public int getOpcode ()
    {
	return opcode_;
    }

    /**
     * Set opcode of this event
     */
    public void setOpcode (int opcode)
    {
	opcode_ = opcode;
    }

    /**
     * Get request id
     */
    public int getEventid ()
    {
	return eventid_;
    }

    /**
     * Set request id
     */
    public void setEventid (int eventid)
    {
	eventid_ = eventid;
    }

    /**
     * Get client id
     */
    public int getClientid ()
    {
	return clientid_;
    }

    /**
     * Set client id
     */
    public void setClientid (int clientid)
    {
	clientid_ = clientid;
    }

    /**
     * Get cbk id
     */
    public int getCbkid ()
    {
	return cbkid_;
    }

    /**
     * Set cbk id
     */
    public void setCbkid (int cbkid)
    {
	cbkid_ = cbkid;
    }

    /**
     * Get socket id
     */
    public int getSocketid ()
    {
	return socketid_;
    }

    /**
     * Set socket id
     */
    public void setSocketid (int socketid)
    {
	socketid_ = socketid;
    }

    /**
     * Get Status of event
     */
    public int getStatus ()
    {
	return status_;
    }

    /**
     * Set Status Field
     */
    public void setStatus (int status)
    {
	status_ = status;
    }

    /**
     * Get Data Field
     */
    public rsvcData getData ()
    {
	return data_;
    }

    /**
     * Set Data Field
     */
    public void setData (rsvcData data)
    {
	data_ = new rsvcData (data);
    }

    /**
     * Set Handler field
     */
    public void setHandler (rsvcEventHandler handler)
    {
	handler_ = handler;
    }

    /**
     * Get handler field
     */
    public rsvcEventHandler getHandler () throws NullPointerException
    {
	if (handler_ == null) {
	    throw new NullPointerException ("rsvcEvent has a null handler");
	}
	return handler_;
    }

    /**
     * Return binary data stream size for this event
     */
    public int streamSize ()
    {
	int dsize = 0;
	int size = 0;
	
	// magic number first
	dsize += rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM);

	// size of the data to follow after this
	dsize += rsvcDataOutputStream.streamSize (size);

	// size of 6 integer fields
	dsize += 6*rsvcDataOutputStream.streamSize ((int)0);

	dsize += data_.streamSize ();

	return dsize;
    }

    /**
     * Convert object into a binary data stream
     */
    public void streamOut (OutputStream output) throws IOException
    {
	// calculate total size of this binary stream
	int binarysize = streamSize ();

	// payload size without magic number and size information
	int rsize = binarysize - 
	    rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM) -
	    rsvcDataOutputStream.streamSize (binarysize);

	rsvcDataOutputStream writer = new rsvcDataOutputStream (output);

	// write out magic number first
	try{
	    writer.write (rsvcData._RSVC_MAGIC_NUM);
	}catch (IOException e) {
	    throw e;
	}
	
	try {
	    writer.write (rsize);
	}catch (IOException e) {
	    throw e;
	}

	// write out six integer field
	try {
	    writer.write (opcode_);
	}catch (IOException e) {
	    throw e;
	}

	try {
	    writer.write (cbkid_);
	}catch (IOException e) {
	    throw e;
	}

	try {
	    writer.write (eventid_);
	}catch (IOException e) {
	    throw e;
	}

	try {
	    writer.write (clientid_);
	}catch (IOException e) {
	    throw e;
	}
	      
	try {
	    writer.write (socketid_);
	}catch (IOException e) {
	    throw e;
	}

	try {
	    writer.write (status_);
	}catch (IOException e) {
	    throw e;
	}

	// finally data item itself
	try {
	    data_.streamOut (writer);
	}catch (IOException e) {
	    throw e;
	}
    }

    /**
     * Read header information of an incoming stream to find out 
     * size information of data stream n
     */
    public static int readHeader (InputStream stream) throws IOException
    {    
	// attach input stream
	rsvcDataInputStream input = new rsvcDataInputStream (stream);

	// read magic number first
	int magic;
	try {
	    magic = input.readInt ();
	}catch (IOException e){
	    throw e;
	}

	if (magic != rsvcData._RSVC_MAGIC_NUM) {
	    throw new IOException ("Magic number mismatch");
	}	

	// get data size
	int datasize;
	try {
	    datasize = input.readInt ();
	}catch (IOException e) {
	    throw e;
	}
	return datasize;
    }

    /**
     * Return streamed event header length
     */
    public static int headerLen ()
    {
	return rsvcDataOutputStream.streamSize (rsvcData._RSVC_MAGIC_NUM) +
	    rsvcDataOutputStream.streamSize ((int)1);
    }

    /**
     * Convert a stream into an event object
     */
    public void streamIn (InputStream stream) throws IOException
    {
	// clean up this object
	cleanup ();

	// attach input stream
	rsvcDataInputStream input = new rsvcDataInputStream (stream);

	try {
	    opcode_ = input.readInt ();
	} catch (IOException e) {
	    throw e;
	}

	try {
	    cbkid_ = input.readInt ();
	} catch (IOException e) {
	    throw e;
	}

	try {
	    eventid_ = input.readInt ();
	} catch (IOException e) {
	    throw e;
	}

	try {
	    clientid_ = input.readInt ();
	} catch (IOException e) {
	    throw e;
	}

	try {
	    socketid_ = input.readInt ();
	} catch (IOException e) {
	    throw e;
	}

	try {
	    status_ = input.readInt ();
	} catch (IOException e) {
	    throw e;
	}

	try {
	    data_.streamIn (input);
	}catch (IOException e) {
	    throw e;
	}
    }

    public String toString () 
    {
	StringBuffer result = new StringBuffer ();

	result.append ("Event Contains \n");
	result.append ("opcode: ").append (opcode_).append ("\n");
	result.append ("cbkid:  ").append (cbkid_).append ("\n");
	result.append ("eventid:  ").append (eventid_).append ("\n");
	result.append ("clientid:  ").append (clientid_).append ("\n");	
	result.append ("socketid:  ").append (socketid_).append ("\n");
	result.append ("status:  ").append (status_).append ("\n");
	result.append (data_.toString());

	return result.toString();
    }

}


	

	    

