/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/02/08
// RCS-ID:      $Id: debuggerpl.h,v 1.4 2001/04/04 12:42:36 aleksandras Exp $
// Copyright:   (c) Aleksandras Gluchovas (alex@soften.ktu.lt)
// Licence:   	GPL (version 2.0 or later)
/////////////////////////////////////////////////////////////////////////////

#ifndef __WXSDEBUGGERPL_G__
#define __WXSDEBUGGERPL_G__

#include "wx/pmf/pm.h"

#include "wx/dynarray.h"
#include "wx/hash.h"
#include "wx/list.h"
#include "wx/socket.h"
#include "wx/thread.h"

// FOR NOW::
class wxsPluginBase {};

//class wxObject { ~wxObject() {} };

// Note: all debugging related helper-classes are prefixed with "wxsDbg"

typedef long DbgObjId_t;

const DbgObjId_t INVALID_DBG_OBJ_ID = DbgObjId_t(-1);
const size_t     INVALID_SIZE_VALUE = (size_t)(-1);

// enums, see actual objects which use them

enum wxsDbgStepTypesEnum
{
	wxsDbg_STEP_INTO,
	wxsDbg_STEP_LINE,
	wxsDbg_STEP_OUT,
	wxsDbg_STEP_OVER
};

enum wxdDbgThreadStatusEnum
{
	wxsDbg_THREAD_RUNNING,
	wxsDbg_THREAD_WAITING,
	wxsDbg_THREAD_SLEEPING,
	wxsDbg_THREAD_ZOMBIE,
	wxsDbg_THREAD_MONITOR,

	wxsDbg_THREAD_SUSPENDED  // FOR NOW:: quick but incorrect!
};

enum wxsDbgTypeFlagsEnum
{
	wxsDbg_VIRTUAL_FLAG   = 0x01,
	wxsDbg_STATIC_FLAG    = 0x02,
	wxsDbg_FINAL_FLAG     = 0x04,
	wxsDbg_VOLATILE_FLAG  = 0x08,
	wxsDbg_TRANSIENT_FLAG = 0x10
};

enum wxsDbgTypesEnum
{
	wxsDbg_BYTE_TYPE          = 0x0001,
	wxsDbg_CHAR_TYPE          = 0x0002,
	wxsDbg_COMPOSITE_TYPE     = 0x0004, // classes/structures/interfaces
	wxsDbg_FLOAT_TYPE         = 0x0008,
	wxsDbg_DOUBLE_TYPE        = 0x0010,
	wxsDbg_INT_TYPE           = 0x0020,
	wxsDbg_LONG_TYPE          = 0x0040,
	wxsDbg_SHORT_TYPE         = 0x0080,
	wxsDbg_VOID_TYPE          = 0x0100,
	wxsDbg_BOOLEAN_TYPE       = 0x0200,
	wxsDbg_STRING_TYPE        = 0x0400,

	wxsDbg_UNKNOWN_TYPE       = 0x0800,

	wxsDbg_ARRAY_TYPE_FLAG    = 0x1000,
	wxsDbg_POINTER_TYPE_FLAG  = 0x2000,
	wxsDbg_UNSIGNED_TYPE_FLAG = 0x4000,
	wxsDbg_TYPES_MASK		  = 0x0FFF
};

// forward decls.

class wxsDebuggerEngine;

/*
 * base class for classes to represents object in the debugger's 
 * address space and mirrors the actual object in the debugged process,
 * the actual object is referenced only by it's id
 */

class wxsDbgMirror : public wxObject
{
public:
	wxsDbgMirror();

	virtual DbgObjId_t GetId();
	virtual void SetId( DbgObjId_t id );
	virtual ~wxsDbgMirror();

	wxsDebuggerEngine& GetDebugger() const;

protected:
	DbgObjId_t mId;
};

// containers

WX_DEFINE_ARRAY( wxsDbgMirror*, wxsDbgMirrorListT );
typedef wxArrayLong wxsDbgObjectIdListT;

// global helpers

wxsDebuggerEngine& wxsGetDbg();
void wxsSetDbg( wxsDebuggerEngine* pPlugin );

// NOTE:: all the debug-objects are kinds of wxsDbgMirror

class wxsDbgThread : public wxsDbgMirror
{
public:
	wxString mName;
	bool   mIsSuspended;

	void SetName( const wxString& name ) { mName = name; }
	wxString GetName() { return mName; }
};

class wxsDbgThreadGroup : public wxsDbgMirror
{
public:
	wxsDbgMirrorListT mThreads;
	wxsDbgMirrorListT mGroups;
	wxString            mName;

	void SetName( const wxString& name ) { mName = name; }
};

class wxsDbgLocation : public wxsDbgMirror
{
public:

	enum ResolutionStates
	{
		INVALID,                // not initialized
		RESOLVED_FOR_FRONTEND,  // resolved only for backend
		RESOLVED_FOR_BACKEND,	// resolved only for frontend
		RESOLVED				// resolved for both backend and frontend
	};

	wxsDbgLocation();

	wxsDbgLocation( const wxPMFileInfo& file, size_t line );

	wxsDbgLocation( DbgObjId_t classId,
					DbgObjId_t methodId,
					DbgObjId_t instructionId );

	bool IsResolved() const ;
	int  GetResolutionState() const;
	bool Resolve() const;

	void SetResolutionState( int state );
	void SetupForBackend( DbgObjId_t classId,
						  DbgObjId_t methodId,
						  DbgObjId_t instructionId );

	void SetupForFrontend( const wxPMFileInfo& file, size_t line );
	void SetFile( const wxPMFileInfo& file );
	void SetLine( size_t line );

	// returns combined human-readable name, can be used by frontends

	wxString GetDisplayText() const;

	size_t  GetLine() const;
	const wxPMFileInfo& GetFile() const;

	DbgObjId_t GetClassId() const;
	DbgObjId_t GetMethodId() const;
	DbgObjId_t GetInstructionId() const;

	bool operator==( const wxsDbgLocation& other ) const;

protected:

	// for the back-end
	DbgObjId_t mClassId;
	DbgObjId_t mMethodId;
	DbgObjId_t mInstructionId;

	// resolution for the front-end
	size_t    mLine;
	wxPMFileInfo  mFile;

	int     mState;
};

class wxsDbgType : public wxsDbgMirror
{
public:
	wxsDbgType();

	virtual wxString GetName();
	virtual void SetName( const wxString& name );
	
	virtual wxString GetSignature();
	virtual void SetSignature( const wxString& s );

	virtual int  GetFlags();
	virtual void SetFlags( int flags );

	virtual int GetTypeCode(); // see wxsDbgTypesEnum
	virtual void SetTypeCode( int tcode );

public:
	wxString mName;
	wxString mSignature;
	int    mFlags;  // see wxsDbgTypeFlagsEnum
	int    mTypeCode;
};

// classes/interfaces/stuctures are all represented
// by composite type

class wxsDbgCompositeType : public wxsDbgType
{
public:
	wxsDbgCompositeType();
	~wxsDbgCompositeType();

	virtual wxsDbgMirrorListT& GetMethods();
	virtual wxsDbgMirrorListT& GetFields();

	virtual void SetMethods( wxsDbgMirrorListT& methods );
	virtual void SetFields( wxsDbgMirrorListT& fields );

protected:
	bool mMethodsLoaded;
	bool mFieldsLoaded;

	wxsDbgMirrorListT mFields;
	wxsDbgMirrorListT mMethods;
};

class wxsDbgMethod : public wxsDbgType
{
public:
	wxsDbgMethod();
	~wxsDbgMethod();

	virtual wxArrayInt& GetLines();
	virtual wxArrayInt& GetCodeIndexes();
	virtual wxsDbgMirrorListT& GetArgumentTypes();
	virtual wxStringList& GetArgumentNames();

	virtual void SetLines( wxArrayInt& lines );
	virtual void SetCodeIndexes( wxArrayInt& lst );
	virtual void SetArgTypes( wxsDbgMirrorListT& types );
	virtual void SetArgNames( wxStringList& names );

	virtual wxsDbgCompositeType* GetContainingType();
	virtual void SetContainingType( wxsDbgCompositeType* pType );

protected:
	wxArrayInt       mLines;
	wxArrayInt       mCodeIndexes;

	bool           mLineInfoLoaded;
	bool           mArgInfoLoaded;

	wxsDbgMirrorListT mArgTypes;
	wxStringList      mArgNames;

	wxsDbgCompositeType* mpContainingType;
};

class wxsDbgField : public wxsDbgMirror
{
public:
	wxsDbgField();

	wxString&		GetName();
	wxsDbgType& GetDeclaringType();

	DbgObjId_t  GetDeclaringTypeId();
	void SetDeclaringType( wxsDbgType* pType );

	void SetName( const wxString& name );
	void SetSignature( const wxString& sign );

	const wxString& GetSignature();

	virtual wxsDbgCompositeType* GetContainingType();
	virtual void SetContainingType( wxsDbgCompositeType* pType );

protected:
	wxString	mName;
	wxString	mSignature;
	DbgObjId_t  mDeclTypeId;
	wxsDbgType* mpDeclType;

	wxsDbgCompositeType* mpContainingType;
};

class wxsDbgLocalVariable : public wxsDbgType
{
public:
	bool mIsArgument;
};

class wxsDbgValue : public wxsDbgMirror
{
public:
	virtual int GetGeneralType() = 0;
};

class wxsDbgObjectValue : public wxsDbgValue
{
public:
	virtual int GetGeneralType();

	wxsDbgType* GetDynamicType();
	wxsDbgMirrorListT& GetFieldValues( wxsDbgType& forType );
public:
	wxsDbgMirrorListT mValues;
	bool              mValuesLoaded;
	wxsDbgType*    	  mpType;
};

class wxsDbgArrayValue : public wxsDbgValue
{
public:
	virtual int GetGeneralType();

	size_t GetCount();
	wxsDbgMirrorListT& GetValues();
	bool HasStringValue();
	wxString GetStringValue();

protected:
	wxsDbgMirrorListT mValues;
	bool           mValuesLoaded;
};

class wxsDbgPrimitiveValue : public wxsDbgValue
{
public:
	virtual int GetGeneralType();

	long GetDecimalValue();
	wxString GetStringValue();

protected:
	// "variant" data
	long   mDecValue;
	wxString mStrValue;
};

class wxsDbgValueTreeNode : public wxObject
{
public:
	wxsDbgValueTreeNode();
	~wxsDbgValueTreeNode();

	void AddChild( wxsDbgValueTreeNode* pNode );
	wxsDbgMirrorListT& GetChildren();

	wxString GetErrorMessage();
	wxString& GetName();
	wxsDbgMirrorListT& GetFieldValues();
	wxsDbgValue& GetValue();

	wxsDbgType& GetDeclaringType();
	void SetField( wxsDbgField* pField );
	void SetDeclaringType( wxsDbgType* pType );
	void SetValue( wxsDbgValue* pValue );
	void SetFieldValues( wxsDbgMirrorListT& fieldValues );
	void SetIsResolved( bool resolved );

	void ExpandNode();   // adds all possible children
	void CollapseNode(); // removes all current children
	bool IsExpanded();
	void InvalidateNode(); // marks this node an all it's subchildren
						   // as unresolved
	wxsDbgType& GetType();
	bool IsResolved();


public:
	bool              mValueResolved;
	bool              mIsExpanded;
	wxString            mErrorMsg;
	wxsDbgMirrorListT mChildNodes; // NOTE:: this list contains elements derived from
								   //        wxObject directly, therefore the type of
								   //        container for the is from, but ofcause
								   //        this FOR NOW::

	wxString            mName;      // node of the variable, relevant to both
								  // on-stack and object-field variables

	wxsDbgType*       mpDeclType; // valid, if the node maps to the on-stack value
	wxsDbgField*      mpField;    // valid, if the node maps to the field of an object

	wxsDbgValue*      mpValue;
	wxsDbgMirrorListT mFieldValues;
};

class wxsDbgStackFrame : public wxsDbgMirror
{
public:
	wxsDbgStackFrame();
	~wxsDbgStackFrame();

	void SetLocation( const wxsDbgLocation& loc );
	wxsDbgLocation& GetLocation();

	void SetDisplayText( const wxString& text );
	wxString& GetDisplayText();

	// returns instances of wxsDbgField

	wxsDbgMirrorListT& GetLocals(); 

	// returns instances of wxsDbgValue

	wxsDbgMirrorListT& GetValuesOfLocals();

	void SetLocals( wxsDbgMirrorListT& locals );
	void SetValuesOfLocals( wxsDbgMirrorListT& values );

	// returns NULL, for static methods

	wxsDbgValue* GetThisObject();
	void SetThisThisObject( wxsDbgValue* pThisValue );

protected:
	wxsDbgLocation	  mLocation;
	DbgObjId_t        mThisObjId;

	wxsDbgValue*      mpThisObj;
	bool              mLocalsLoaded;
	bool              mValuesLoaded;
	wxsDbgMirrorListT mLocals;  // instances of wxsDbgField
	wxsDbgMirrorListT mValues;  // instances of wxsDbgValue

	wxString            mDisplayText;
};

class wxsDbgEventRequest : public wxsDbgMirror
{
public:
};

class wxsDbgEvent : public wxsDbgMirror
{
public:
	DbgObjId_t mReqId;
};

class wxsDbgBreakpoint : public wxsDbgEventRequest
{
public:
	wxsDbgBreakpoint();

	const wxsDbgLocation& GetLocation();
	void SetLocation( const wxsDbgLocation& where );

	void SetEnabled( bool enabled );
	bool IsEnabled();

protected:
	wxsDbgLocation mLocation;
	bool           mIsEnabled;
};

class wxsDbgStepRequest : public wxsDbgEventRequest
{
public:
	int mStepType;
};

class wxsDbgWatchpoint : public wxsDbgEventRequest
{
public:
	wxsDbgField mField;
};

class wxsDebuggerListener 
{
public:
	virtual void OnThreadStarted( wxsDbgThread* pThread ) {}
	virtual void OnThreadFinished( wxsDbgThread* pThread ) {}
	virtual void OnThreadResumed( wxsDbgThread* pThread ) {}
	virtual void OnThreadSuspended( wxsDbgThread* pThread ) {}

	// pThread is NULL if active thread has finshed or reset

	virtual void OnActiveThreadSet( wxsDbgThread* pThread ) {}
	
	virtual void OnBreakpointHit( wxsDbgBreakpoint* pBrk, wxsDbgThread* pThread ) {}
	virtual void OnCurrentStackFrameChanged( wxsDbgStackFrame* pFrame, int no ) {}
	virtual void OnStepCompleted( wxsDbgThread* pThread, wxsDbgLocation& where ) {}

	virtual void OnProcessStarted( int pid ) {}
	virtual void OnProcessTerminated( int pid ) {}
	virtual void OnStackFramePushed( wxsDbgThread* pThread ) {}
	virtual void OnStackFramePopped( wxsDbgThread* pThread ) {}
};

WX_DEFINE_ARRAY( wxsDebuggerListener*, wxsDebuggerListenerListT );

class wxsJDWPBackend;

// FOR NOW:: hack
typedef wxsJDWPBackend wxsDebuggerBackend;

//class wxsDebuggerBackend;

class wxsDebuggerEngine : public wxObject
{
public:
	wxsDebuggerEngine();
	~wxsDebuggerEngine();

	void AddListener( wxsDebuggerListener* pListener );
	void RemoveListener( wxsDebuggerListener* pListener );

	virtual void SetBackend( wxsDebuggerBackend* pBackend );

	virtual bool GetLocalSymbols( wxStringList& lst );

	// returns TRUE if value of the symbol is resolved in the
	// current context, otherwise returns FALSE and value constains
	// wxString with error message explaining failure

	virtual bool GetSymbolValue( const wxString& name, wxString& value, bool& isComposite );

	// retrieval of meta-information

	virtual wxsDbgType* FindTypeBySignature( const wxString& sign );

	// each item in the given list is a root node (wxsDbgValueTreeNode) of a value-tree

	virtual void LoadNodeValuesRecursive( wxsDbgValueTreeNode* pNode );
	virtual bool ResolveRoots( wxsDbgMirrorListT& trees, bool localsOnly );
	virtual bool LoadValueTrees( wxsDbgMirrorListT& trees, bool localsOnly );

	virtual size_t GetStackFrameCount();

	// stack frames count from 0 to n. 0th being the top-frame
	virtual bool GetStackFrames( size_t from, size_t till, wxsDbgMirrorListT& lst );

	virtual size_t GetCurrentStackFrameNo();
	virtual bool   SetCurrentStackFrameNo( size_t no );
	virtual wxsDbgStackFrame* GetCurrentStackFrame();

	// breakpoints

	virtual wxsDbgMirrorListT& GetBreakpoints();
	virtual wxsDbgBreakpoint* AddBreakpoint( const wxsDbgLocation& where, int hitCount = 0 );
	virtual bool RemoveBreakpoint( const wxsDbgLocation& where );
	virtual bool RemoveBreakpoint( wxsDbgBreakpoint* pBrkPoint );
	virtual bool RemoveAllBreakpoints();

	// threads

	virtual bool SetCurrentThread( wxsDbgThread* pThread );
	virtual wxsDbgThread* GetCurrentThread();

	virtual bool GetTopLevelThreadGroups( wxsDbgMirrorListT& lst );
	virtual bool GetThreadsInGroup( wxsDbgThreadGroup* pGroup, wxsDbgMirrorListT& lst );
	virtual bool GetGroupsInGroup( wxsDbgThreadGroup* pGroup, wxsDbgMirrorListT& lst );

	virtual bool SuspendThread( wxsDbgThread* pThread );
	virtual bool ResumeThread( wxsDbgThread* pThread );
	virtual wxString GetDebbugerBackendVersion();

	virtual bool InterruptCurrentThread();
	virtual bool StepCurrentThread( wxsDbgStepTypesEnum stepType );
	virtual bool ResumeCurrentThread();

	// NOTE:: value of args is opque, has meaning only to a concrete 
	//        debugger backend

	virtual bool AttachToProcess( const wxString& args );
	virtual bool StartProcess( const wxString& args );
	virtual bool StopProcess();
	virtual bool RunProcess();

	// blocks the caller thread until the next event arrives to the 
	// event queue, or returns immediately if the queue is not empty.
	// Method can be used by console debugger-frontends, to block
	// until the request is completed or any other event occured
	//
	// RETURN: false, if error occured

	virtual bool WaitForEvents();

	// utilities called by mirror classes for loading 
	// of their internal infos on-demand

	virtual bool LoadMethods( wxsDbgCompositeType& ctype );
	virtual bool LoadFields( wxsDbgCompositeType& ctype );
	virtual bool LoadDeclaringType( wxsDbgField& field );
	virtual bool LoadLines( wxsDbgMethod& mtd );
	virtual bool LoadArguments( wxsDbgMethod& mtd );

	virtual bool ResolveLocation( wxsDbgLocation& loc );

	// lower-level queries invoked by back-end plugins

	virtual wxsDbgType* FindTypeById( DbgObjId_t typeId );
	virtual bool AddType( wxsDbgType* pType );

	//////////////////////////////////////////////////////////
	// Notifications received from backend-debugger plugins	//
	//////////////////////////////////////////////////////////

	virtual void OnThreadStarted  ( DbgObjId_t threadId );
	virtual void OnThreadFinished ( DbgObjId_t threadId );
	virtual void OnThreadResumed  ( DbgObjId_t threadId );
	virtual void OnThreadSuspended( DbgObjId_t threadId );

	// pThread is NULL if active thread has finshed or reset
	virtual void OnActiveThreadSet( DbgObjId_t threadId );
	
	virtual void OnBreakpointHit( DbgObjId_t brkId, DbgObjId_t threadId, wxsDbgLocation where );
	virtual void OnCurrentStackFrameChanged( DbgObjId_t frameId, int no );
	virtual void OnStepCompleted( DbgObjId_t threadId, wxsDbgLocation where );
	virtual void OnProcessStarted( int pid );
	virtual void OnProcessTerminated( int pid );
	virtual void OnStackFramePushed( DbgObjId_t threadId, wxsDbgLocation where );
	virtual void OnStackFramePopped( DbgObjId_t threadId, wxsDbgLocation where );

	virtual bool StopDebugger();
	virtual bool DetachDebugger();

	// helper methods

	wxsDbgBreakpoint* FindBreakpointById( DbgObjId_t brkPointId );
	wxsDbgThread* FindThreadById( DbgObjId_t threadId );

	// invoked only by back-end debugger plugins

	virtual void SetLastError( const wxString& msg );
	virtual wxString GetLastError();

protected:
	wxHashTable       mTypeIdsHash;    // classId <-> wxsDbgCompositeType
	wxHashTable		  mTypeNamesHash;  // typeName <-> wxsDbgCompositeType
	wxsDbgMirrorListT mTypes;

	wxsDbgMirrorListT mAllThreadGroups;
	wxsDbgMirrorListT mAllThreads;
	wxsDbgMirrorListT mStackFrames;
	wxsDbgMirrorListT mBreakpoints;

	size_t            mCurrentStackFrame;
	wxsDbgThread*     mpCurrentThread;
	wxString            mLastErrorMsg;

	wxsDebuggerBackend* mpBackend;
	wxsDebuggerListenerListT      mListeners;
};

///////////////////////////////////////////////////////////////////////////////
/////////// sample implementation of debugger backend on top of JDWP //////////
///////////////////////////////////////////////////////////////////////////////

class wxsJDWPPacket
{
public:
	wxsJDWPPacket();
	wxsJDWPPacket( int cmdSetId, int cmdId );

	bool ParseStream( char* buf, size_t len );

	size_t GetSize();

	void Create( int cmdSetId, int cmdId );

	void FinalizePacket();
	wxString& GetPacketData();
	DbgObjId_t GetPacketId();
	int GetCommandSetId();
	int GetCommandId();
	bool HasError();
	int GetErrorCode();

	// stream-parsing helpers

	void WriteByte( char ch );
	void WriteInt( int i );
	void WriteLong( long l );
	void WriteObjId( DbgObjId_t id );
	void WriteMethodId( DbgObjId_t id );
	void WriteString( const wxString& s );
	void WriteLocation( const wxsDbgLocation& where );

	unsigned char ReadByte();
	int		   ReadInt();
	long	   ReadLong();
	DbgObjId_t ReadObjId();
	DbgObjId_t ReadMethodId();
	wxString	   ReadString();
	wxsDbgLocation ReadLocation();

protected:
	wxString mData;
	size_t mReadHead;
	int    mPacketId;
	char   mFlags;
	short  mErrorCode;
	int    mCmdSetId;
	int    mCmdId;

	static int mPacketGen;
};

WX_DEFINE_ARRAY( wxsJDWPPacket*, wxsJDWPPacketPacketListT );

//class wxsJDWPBackend : public wxsDebuggerBackend

class wxsJDWPBackend : public wxThread
{
public:
	wxsJDWPBackend();
	virtual ~wxsJDWPBackend();

	// args - "host:port" (host can be either literal or dot-number)

	virtual bool AttachToProcess( const wxString& args );

	// args - fully qualified name of the class, e.g. "myapackage.MyClass";

	virtual bool StartProcess( const wxString& args );
	virtual bool RunProcess();

	virtual void DetachFromProcess();
	virtual bool StopProcess();

	virtual wxString GetDebuggerBackendVersion();

	virtual void SetFrontend( wxsDebuggerEngine* pFrontend );

	virtual bool AddBreakpoint( const wxsDbgLocation& where, DbgObjId_t& brkPointId, int hitCount );

	virtual bool RemoveBreakpoint( DbgObjId_t brkPointId );
	virtual bool RemoveAllBreakpoints();

	virtual bool StepThread( DbgObjId_t threadId, wxsDbgStepTypesEnum stepType );

	virtual bool InterruptThread( DbgObjId_t threadId );
	virtual bool SuspendThread( DbgObjId_t threadId );
	virtual bool ResumeThread( DbgObjId_t threadId );

	virtual bool GetAllThreads( wxsDbgObjectIdListT& lst );
	virtual bool GetAllThreadGroups( wxsDbgObjectIdListT& lst );
	virtual bool GetThreadName( DbgObjId_t threadId, wxString& name );
	virtual bool GetThreadGroupName( DbgObjId_t groupId, wxString& name );

	virtual int GetThreadStatus( DbgObjId_t threadId );

	virtual int GetStackFrameCount( DbgObjId_t threadId );
	virtual bool GetStackFrames( DbgObjId_t threadId,
								 size_t from, size_t till, wxsDbgMirrorListT& frames );

	virtual bool ResolveLocation( wxsDbgLocation& where );

	virtual wxsDbgType* LoadTypeBySignature( const wxString& sign );

	virtual bool LoadMethods( wxsDbgCompositeType* pType );
	virtual bool LoadFields( wxsDbgCompositeType* pType );
	virtual bool LoadLineTables( wxsDbgMirrorListT& forMethods );

	virtual bool WaitForEvents();

protected:
	
	void LoadAllClasses();

	// backend-specific methods

	void PacketReceiverThread();
	void DeliverPacket( wxsJDWPPacket& packet );

	void SuspendReceiver();
	void ResumeReceiver();
	void StopDeliveryThread( int reason );

	bool GetClassSignatureFromFile( const wxPMFileInfo& file );

	// RETURN: packet id

	int SendPacket( wxsJDWPPacket& packet );

	// RETURN: FALSE, if wait failed

	bool WaitForResponse( int reqPacketId, wxsJDWPPacket& respPacket );

	// entry of 7packet-receiver thread
	virtual void * Entry();


protected:
	wxsDebuggerEngine*  mpEngine;

	// lists and queues

	wxsDbgObjectIdListT	mOutgoingRequests;

	wxsJDWPPacketPacketListT mPacketQueue;
	wxMutex					 mPacketQueueLock;
	wxMutex					 mPacketRomovalLock;

	// events and mutecies

	wxMutex            mRequestsLock;
	wxMutex            mIPCChannelLock;

	wxCondition        mResumeEvent;
	wxCondition        mPacketReceivedEvent;

	// TODO:: abstraction of IPC channel

	wxSocketClient mSock;
	int            mDbgPID;

	bool		   mClassesPreloaded;

	wxsJDWPPacket mRespPacket;
};

enum JDWPCommandSets
{
	// sets for request-packets

	CS_VirtualMachine = 1,
	CS_ReferenceType = 2,
	CS_ClassType = 3,
	CS_ArrayType = 4,
	CS_InterfaceType = 5,
	CS_Method = 6,
	CS_Field = 8,
	CS_ObjectReference = 9,
	CS_StringReference = 10,
	CS_ThreadReference = 11,
	CS_ThreadGroupReference = 12,
	CS_ArrayReference = 13,
	CS_ClassLoaderReference = 14,
	CS_EventRequest = 15,
	CS_StackFrame = 16,
	CS_ClassObjectReference = 17,

	// sets for response-packets

	CS_Event= 64,
};

enum JDWPCommands
{
	 // VirtualMachine Command Set (1)

     CMD_Version = 1,
     CMD_ClassesBySignature = 2,
     CMD_AllClasses = 3,
     CMD_AllThreads = 4, 
     CMD_TopLevelThreadGroups = 5, 
     CMD_Dispose = 6, 
     CMD_IDSizes = 7, 
     CMD_SuspendVM = 8, 
     CMD_ResumeVM = 9, 
     CMD_Exit = 10, 
     CMD_CreateString = 11, 
     CMD_Capabilities = 12, 
     CMD_ClassPaths = 13, 
     CMD_DisposeObjects = 14,
     CMD_HoldEvents = 15, 
     CMD_ReleaseEvents = 16,

	 // ReferenceType Command Set (2) 

     CMD_Signature = 1, 
     CMD_ClassLoader = 2, 
     CMD_Modifiers = 3, 
     CMD_Fields = 4, 
     CMD_Methods = 5, 
     CMD_GetRefValues = 6, 
     CMD_SourceFile = 7, 
     CMD_NestedTypes = 8, 
     CMD_ref_Status = 9, 
     CMD_Interfaces = 10, 
     CMD_ClassObject = 11,
	 
// ClassType Command Set (3)

     CMD_Superclass = 1, 
     CMD_SetValues = 2, 
     CMD_InvokeClassMethod = 3, 
     CMD_NewClassInstance = 4, 

// ArrayType Command Set = 4; 

     CMD_NewArrayInstance = 1, 

// InterfaceType Command Set (5)

// Method Command Set (6)

     CMD_LineTable = 1, 
     CMD_VariableTable = 2, 
     CMD_Bytecodes = 3, 

// Field Command Set (8)

// ObjectReference Command Set (9)

     CMD_ReferenceType = 1, 
     CMD_GetObjRefValues = 2, 
     CMD_SetObjRefValues = 3, 
     CMD_MonitorInfo = 5, 
     CMD_InvokeMethod = 6, 
     CMD_DisableCollection = 7, 
     CMD_EnableCollection = 8, 
     CMD_IsCollected = 9, 

// StringReference Command Set (10)

     CMD_Value = 1, 

// ThreadReference Command Set (11)

     CMD_ThreadName = 1, 
     CMD_Suspend = 2, 
     CMD_Resume = 3, 
     CMD_Status = 4, 
     CMD_ThreadGroup = 5, 
     CMD_Frames = 6, 
     CMD_FrameCount = 7, 
     CMD_OwnedMonitors = 8, 
     CMD_CurrentContendedMonitor = 9, 
     CMD_Stop = 10, 
     CMD_Interrupt = 11, 
     CMD_SuspendCount = 12, 

// ThreadGroupReference Command Set (12)

     CMD_GroupName = 1, 
     CMD_Parent = 2, 
     CMD_Children = 3, 

// ArrayReference Command Set (13)

     CMD_Length = 1, 
     CMD_GetArrayValues = 2, 
     CMD_SetArrayValues = 3, 

// ClassLoaderReference Command Set (14)

     CMD_VisibleClasses = 1, 

// EventRequest Command Set (15)

     CMD_Set = 1, 
     CMD_Clear = 2, 
     CMD_ClearAllBreakpoints = 3, 

// StackFrame Command Set (16)

     CMD_GetFrameValues = 1, 
     CMD_SetFrameValues = 2, 
     CMD_ThisObject = 3, 

// ClassObjectReference Command Set (17)

     CMD_ReflectedType = 1, 

// Event Command Set (16)

     CMD_Composite = 100 
};

enum JWPDEvents
{
	EVT_VM_DISCONNECTED = 100,
	EVT_METHOD_EXIT = 41,
	EVT_EXCEPTION_CATCH = 30,
	EVT_USER_DEFINED = 5,
	EVT_METHOD_ENTRY = 40,
	EVT_VM_DEATH = 99,
	EVT_CLASS_UNLOAD = 9,
	EVT_CLASS_PREPARE = 8,
	EVT_SINGLE_STEP = 1,
	EVT_FIELD_MODIFICATION = 21,
	EVT_CLASS_LOAD = 10,
	EVT_THREAD_START = 6,
	EVT_FRAME_POP = 3,
	EVT_VM_INIT = 90,
	EVT_BREAKPOINT = 2,
	EVT_THREAD_END = 7,
	EVT_FIELD_ACCESS = 20,
	EVT_EXCEPTION = 4
};

enum JWPDSuspendPolicies
{
	SPOLICY_NONE = 0,         // suspend no threads when this event is encountered.   
	SPOLICY_EVENT_THREAD = 1, // suspend the event thread when this event is encountered
	SPOLICY_ALL = 2,		  // suspend all threads when this event is encountered.
};

enum JWPDEventModifiers
{
	EMODIFIER_COUNT = 1,
	EMODIFIER_THREAD_ONLY = 3,
	EMODIFIER_CLASS_ONLY = 4,
	EMODIFIER_CLASS_MATCH = 5,
	EMODIFIER_CLASS_EXCLUDE = 6,
	EMODIFIER_LOCATION_ONLY = 7,
	EMODIFIER_EXCEPTION_ONLY = 8,
	EMODIFIER_FIELD_ONLY = 9,
	EMODIFIER_STEP = 10
};


enum JWPDReferenceTypeTagConstants
{
	TAG_CLASS_TYPE = 1,     // ReferenceType is a class
	TAG_INTERFACE_TYPE = 2, // ReferenceType is an interface
	TAG_ARRAY_TYPE = 3      // ReferenceType is an array
};

enum JWPDTagConstants
{
	TAG_ARRAY = 91,            // '[' - an array object (objectID size).   
	TAG_BYTE = 66,             // 'B' - a byte value (1 byte).   
	TAG_CHAR = 67,             // 'C' - a character value (2 bytes).
	TAG_OBJECT = 76,		   // 'L' - an object (objectID size).   
	TAG_FLOAT = 70,			   // 'F' - a float value (4 bytes).   
	TAG_DOUBLE = 68,		   // 'D' - a double value (8 bytes).   
	TAG_INT = 73,			   // 'I' - an int value (4 bytes).   
	TAG_LONG = 74,			   // 'J' - a long value (8 bytes).   
	TAG_SHORT = 83,			   // 'S' - a short value (2 bytes).   
	TAG_VOID = 86,			   // 'V' - a void value (no bytes).   
	TAG_BOOLEAN = 90,		   // 'Z' - a boolean value (1 byte).   
	TAG_STRING = 115,		   // 's' - a String object (objectID size).   
	TAG_THREAD = 116,		   // 't' - a Thread object (objectID size).   
	TAG_THREAD_GROUP = 103,	   // 'g' - a ThreadGroup object (objectID size).   
	TAG_CLASS_LOADER = 108,	   // 'l' - a ClassLoader object (objectID size).   
	TAG_CLASS_OBJECT = 99	   // 'c' - a class object object (objectID size).   
};

enum JWPDThreadStatus
{
	THREAD_RUNNING = 1,
	THREAD_WAIT = 4,
	THREAD_SLEEPING = 2,
	THREAD_ZOMBIE = 0,
	THREAD_MONITOR = 3
};

class wxsDebuggerService : public wxEvtHandler, public wxPMService
{
public:
	wxsDebuggerService();
	~wxsDebuggerService();

	virtual bool Start();
	virtual bool Stop();

	virtual wxPMMergableMenuChain* GetMergableMenuChain();

	virtual wxString GetDisplayName();
	virtual wxString GetDescription();

	virtual wxObject* GetWxObject();

	enum COMMAND_IDS
	{
		ID_START = 100,
		ID_END,
		ID_CONTINUE,
		ID_BREAK,
		ID_GOTOSOURCE,

		ID_STEP_INTO,
		ID_STEP_OVER,
		ID_TOGGLE_BREAKPOINT,
		ID_ADD_WATCH,

		ID_BACKEND_VERSION,
	};

	void OnStart( wxCommandEvent& event );
	void OnEnd( wxCommandEvent& event );
	void OnContinue( wxCommandEvent& event );
	void OnBreak( wxCommandEvent& event );
	void OnGotoSource( wxCommandEvent& event );

	void OnStepInto( wxCommandEvent& event );
	void OnStepOver( wxCommandEvent& event );
	void OnToggleBreakpoint( wxCommandEvent& event );
	void OnAddWatch( wxCommandEvent& event );

	void OnBackendVersion( wxCommandEvent& event );

	DECLARE_EVENT_TABLE()
	DECLARE_DYNAMIC_CLASS( wxsDebuggerService )

protected:
	wxsDebuggerBackend* mpBackend;
	wxsDebuggerEngine*  mpEngine;
};


#endif // __WXSDEBUGGERPL_G__.
