#ifndef BASELOGGER_H_
#define BASELOGGER_H_

#include <jni.h>
#include "TimeUtil.h"

#define CONST_LOADCLASS 1
#define CONST_LOADMETHOD 2
#define CONST_LOADOBJECT 3
#define CONST_UNLOADOBJECT 4
#define CONST_GCSTART 5
#define CONST_GCFINISH 6
#define CONST_THREADSTART 7
#define CONST_THREADEND 8
#define CONST_ENTERMETHOD 9
#define CONST_EXITMETHOD 10
#define CONST_MONITOR_IN 11
#define CONST_MONITOR_OUT 12

#define CONST_CONTENDED_ENTER 13
#define CONST_CONTENDED_ENTERED 14
#define CONST_CONTENDED_EXIT 15
#define CONST_RAW_CONTENDED_ENTER 16
#define CONST_RAW_CONTENDED_ENTERED 17
#define CONST_RAW_CONTENDED_EXIT 18

class BaseLogger
{
public:
	BaseLogger();
	~BaseLogger();
	
	virtual int write(const void * buffer, size_t len) const = 0;
	
	inline void writeString(char * stringValue)
	{
		jshort len = strlen(stringValue);
		write(&len,sizeof(len));
		write(stringValue,sizeof(char) * len);
	}
	
	inline void writeHeader(jbyte header, jlong& time, jlong& clockCPU)
	{
		write(&header,(unsigned int)sizeof(header));
		write(&time,(unsigned int)sizeof(time));
		write(&clockCPU,(unsigned int)sizeof(clockCPU));
	}
	
	inline void writeMainHeader() 
	{
		static const char * progID = (const char *) "DPINSP";
		jint tst = 0xff;
		jlong timeMain = timeUtil.sysTimeMillis();
	
	    write(progID,sizeof(char) * strlen(progID));
	    write(&tst,sizeof(tst));
	    write(&timeMain,sizeof(timeMain));
	}
	
	
	void writeLoadClass(jlong& time,
	                    jlong& clockCPU, 
	                    char *& className, 
	                    jint& classId, 
	                    jint& numberOfMethods) 
	{
		writeHeader(CONST_LOADCLASS,time,clockCPU);
		write(&classId,sizeof(classId));
		writeString(className);
		write(&numberOfMethods,sizeof(numberOfMethods));
	}
	
	
	void writeLoadMethod(jlong& time,
	                    jlong& clockCPU, 
	                    jint& classId,
	                    jint& methodId,
	                    char *& methodName,
	                    char *& signature)
	{
		writeHeader(CONST_LOADMETHOD,time,clockCPU);
		write(&classId,sizeof(classId));
		write(&methodId,sizeof(methodId));
		writeString(methodName);
		writeString(signature);
	}
	
	void writeEnterMethod(jlong& time,
	                      jlong& clockCPU, 
	                      jint& envId,
	                      jint& threadId,
	                      jint& classId,
	                      jint& methodId,
	                      jint& objectId)
    {
    	writeHeader(CONST_ENTERMETHOD,time,clockCPU);
    	write(&envId,sizeof(envId));
    	write(&threadId,sizeof(threadId));
    	write(&classId,sizeof(classId));
    	write(&methodId,sizeof(methodId));
    	write(&objectId,sizeof(objectId));
    }
    
    
    void writeExitMethod(jlong& time,
	                      jlong& clockCPU, 
	                      jint& envId,
	                      jint& threadId,
	                      jint& methodId)
    {
    	writeHeader(CONST_EXITMETHOD,time,clockCPU);
    	
    	write(&envId,sizeof(envId));
    	write(&threadId,sizeof(threadId));
    	write(&methodId,sizeof(methodId));
    }
	
	void writeBeginThread(jlong& time,
	                      jlong& clockCPU, 
	                      jint& envId,
	                      jint& threadId,
	                      char *&threadName)
    {
		writeHeader(CONST_THREADSTART,time,clockCPU);
		
		write(&envId,sizeof(envId));
		write(&threadId,sizeof(threadId));
		writeString(threadName);
	}

    void writeEndThread(jlong& time,
	                      jlong& clockCPU, 
	                      jint& envId,
	                      jint& threadId)
    {
		writeHeader(CONST_THREADSTART,time,clockCPU);
		write(&envId,sizeof(envId));
		write(&threadId,sizeof(threadId));
    }
		
	
	inline TimeUtil getTimeUtil()
	{
		return timeUtil;
	}
	
private:
   TimeUtil timeUtil;
};

#endif /*BASELOGGER_H_*/
