using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using System.Threading;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectPlay;
using Microsoft.DirectX.DirectInput;



using System.Runtime.InteropServices;


namespace DarkStrideToolbox
{	
	public class DSInputWrapper
	{
		#region Properties
		//This is the location of our mouse cursor
		private Vector2 m_oMouseCursorLocation = new Vector2(0,0);

		//This second thread allows our mouse to move smoothly
		private Thread m_oMouseThreadData = null;
		private AutoResetEvent m_oMouseEventFire = null;
		private Microsoft.DirectX.DirectInput.Device m_oMouseDevice = null;

		//Save our toggled states.  For now wejust assume they are off at the start.
		private bool m_bCapsLockToggled = false;
		private bool m_bNumLockToggled = false;

		//07/14/2003 Chris Hill  This variable temporarily holds the exclusive status of the mouse.  Later when we tried
		//to aquire it we will convert this bool value into a flag and load the mouse accordingly.
		private bool m_bMouseInExclusiveMode = true;

		//DirectInput
		private Microsoft.DirectX.DirectInput.Device m_oKeyboardDevice = null;
		private Thread m_oKBThreadData = null;
		private AutoResetEvent m_oKBEventFire = null;

		//This is how we track what key up and down events have occured
		private bool[] m_baLastKeyboardState = null;
		private bool[] m_baLastMouseButtonState = null;


		#region Delegate Variables
		private CallbackMouseUp			m_odDelegate_MouseUp;
		private CallbackMouseDown		m_odDelegate_MouseDown;
		private CallbackMouseWheelMove m_odDelegate_MouseWheelMove;
		private CallbackMouseMoved		m_odDelegate_MouseMoved;

		private CallbackKeyboardKeyDown		m_odDelegate_KeyboardKeyDown;
		private CallbackKeyboardKeyUp		m_odDelegate_KeyboardKeyUp;

		private CallbackError				m_odDelegate_Error;
		#endregion

		private System.Windows.Forms.Control m_oForm = null;
		private System.Windows.Forms.Form m_oTopmostForm = null;

		//12/08/2004 Chris Hill  This tracks weather or not we are in debug mode.  Note that
		//this is different than compile-debug, this is weather or not we write out a log.
		private bool m_bDebugMode = false;
		private string m_sDebugPath = "";

		//03/31/2005 Chris Hill  Sometimes we want to see the absolute position of the mouse, if for example we aren't
		//drawing our own mouse cursor then it has to match exactly.  This property switches us from using DirectInput
		//to using the CLRs built in mouse tracking abilities.
		private bool m_bUseCLRMouseImput = false;
		#endregion

		#region Delegate Variables
		public delegate bool CallbackMouseUp( Vector2 vCurPos,long nButton );
		public delegate bool CallbackMouseDown( Vector2 vCurPos,long nButton );
		public delegate bool CallbackMouseWheelMove( long nDirection );
		public delegate bool CallbackMouseMoved( Vector2 vCurPos,MouseState oMouseStateData,bool[] baButtons );

		public delegate bool CallbackKeyboardKeyDown( Key oKey,bool[] oState );
		public delegate bool CallbackKeyboardKeyUp( Key oKey,bool[] oState );

		public delegate void CallbackError( System.Exception oError );
		#endregion


		public DSInputWrapper(){}


		public void Initialize( System.Windows.Forms.Control oForm )
		{
			m_oForm = oForm;

			//Setup our events for control creation
			this.TopmostForm.Load += new System.EventHandler(this.frmSource_Load);
			this.TopmostForm.Activated += new System.EventHandler(this.frmSource_Activated);


			//Initialize the previous keyboard state
			m_baLastKeyboardState = new bool[ (int)Key.MediaSelect + 1 ];


			//Chris
			//05/06/2005 Chris Hill  If the game engine isn't being initialized until after the form exists then we
			//have to automatically trigger some things.  But if instead it hasn't been then we can't yet and the 
			//form events will handle it for us.
			/*				if( this.TopmostForm.Created == true )
							{
								//12/08/2004 Chris Hill  Record the direct input startup.
								DSMisc.WriteToDebugFile( m_sDebugPath,m_bDebugMode,1,"Input: Topmost form is created, init mouse." );

								InitDirectInput_Mouse();
								InitDirectInput_Keyboard();
							}*/
		}

		public virtual void Dispose()
		{
			if( m_oMouseEventFire != null )
			{
				m_oMouseEventFire.Set();
				m_oMouseEventFire = null;
			}
			if( m_oKBEventFire != null )
			{
				m_oKBEventFire.Set();
				m_oKBEventFire = null;
			}

			if( m_oMouseThreadData != null && m_oMouseThreadData.ThreadState == System.Threading.ThreadState.Running )
			{
				m_oMouseThreadData.Suspend();
			}
			m_oMouseThreadData = null;
			if( m_oKBThreadData != null && m_oKBThreadData.ThreadState == System.Threading.ThreadState.Running )
			{
				m_oKBThreadData.Suspend();
			}
			m_oKBThreadData = null;

			// Unacquire the device one last time just in case 
			if( null != m_oKeyboardDevice ) 
			{
				m_oKeyboardDevice.Unacquire();
				m_oKeyboardDevice.Dispose();
				m_oKeyboardDevice = null;
			}
			if( null != m_oMouseDevice ) 
			{
				m_oMouseDevice.Unacquire();
				m_oMouseDevice.Dispose();
				m_oMouseDevice = null;
			}
		}


		private void frmSource_Load(object sender, System.EventArgs e)
		{
			InitMouse();
			InitKeyboard();
		}
		private void InitMouse()
		{
			//08/09/2005 Chris Hill  You'd think that creating the mouse device would need to be first, but
			//really its not.  Well it could be... never mind.  I am choosing to initialize the mouses starting
			//location first, not that it matters.
			m_oMouseCursorLocation = ConvertWinMousePointToOurMousePoint();


			m_oMouseThreadData = new Thread(new ThreadStart(this.MouseEvent));
			m_oMouseThreadData.IsBackground = true;
			m_oMouseThreadData.Start();
			m_oMouseEventFire = new AutoResetEvent(false);
            
			// Create the device.
			try
			{
				m_oMouseDevice = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Mouse);
			}
			catch(InputException)
			{
				MessageBox.Show("Unable to create device.  Sample will now exit.");
			}

			// Set the cooperative level for the device.
			if( m_bMouseInExclusiveMode == true )
			{
				m_oMouseDevice.SetCooperativeLevel( this.TopmostForm, CooperativeLevelFlags.Exclusive | CooperativeLevelFlags.Foreground );
			}
			else
			{
				m_oMouseDevice.SetCooperativeLevel( this.TopmostForm, CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Foreground );
			}

			// Set a notification event.    
			m_oMouseDevice.SetEventNotification( m_oMouseEventFire );
			// Acquire the device.
			try
			{ 
				m_oMouseDevice.Acquire(); 
			}
			catch{}                
		}

		private void frmSource_Activated(object sender, System.EventArgs e)
		{
			//Acquire the device whenever the application window is activated.
			if (null != m_oMouseDevice)
			{
				try
				{
					m_oMouseDevice.Acquire();
				}
				catch{}
			}

			if (null != m_oKeyboardDevice)
			{
				try
				{
					m_oKeyboardDevice.Acquire();
				}
				catch{}
			}
		}
		private void InitKeyboard()
		{
			Microsoft.DirectX.DirectInput.CooperativeLevelFlags coopFlags;


			m_oKBThreadData = new Thread(new ThreadStart(this.KeyboardEvent));
			m_oKBThreadData.IsBackground = true;
			m_oKBThreadData.Start();
			m_oKBEventFire = new AutoResetEvent(false);

			coopFlags = Microsoft.DirectX.DirectInput.CooperativeLevelFlags.NonExclusive;
			coopFlags |= Microsoft.DirectX.DirectInput.CooperativeLevelFlags.Foreground;

			//Obtain an instantiated system keyboard device.
			try
			{
				m_oKeyboardDevice = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
			}
			catch(InputException)
			{
				MessageBox.Show("Unable to create keyboard device.");
				return;
			}

			m_oKeyboardDevice.SetCooperativeLevel( this.TopmostForm, coopFlags );
			m_oKeyboardDevice.Properties.BufferSize = 8;

			// Set a notification event. 
			m_oKeyboardDevice.SetEventNotification( m_oKBEventFire );
			//Aquire the device
			try
			{
				m_oKeyboardDevice.Acquire();
			}
			catch{}
		}


		//This is the mouse event thread.  This thread will wait until a mouse event occurrs, and invoke
		//the delegate on the main thread to grab the current mouse state and update the UI.
		private void MouseEvent()
		{
			MouseState oMouseStateData;
			bool bAButtonWasPressed = false;
			byte[] byaButtons = null;
			bool[] baButtons = null;


			while( m_oMouseEventFire != null )
			{
				m_oMouseEventFire.WaitOne(-1, false);

				//12/08/2004 Chris Hill  Record the direct input startup.
				DSMisc.WriteToDebugFile( m_sDebugPath,m_bDebugMode,1,"Input: Mouse Event." );

				//Chris					if( m_oMouseEventFire == null ){ continue; }

				try
				{
					m_oMouseDevice.Poll();
				}
				catch
				{
					continue;
				}

				//Chris					if( m_oMouseEventFire == null ){ continue; }

				//10/29/2005 Chris Hill  For whatever reason this fails from time to time and
				//you just have to ignore it.
				//Get the current state of the mouse device.
				try
				{
					oMouseStateData = m_oMouseDevice.CurrentMouseState;

					byaButtons = oMouseStateData.GetMouseButtons();

					//Convert the byte array to a boolean array
					baButtons = new bool[ byaButtons.Length ];
					for( int i=0 ; i<byaButtons.Length ; i++ )
					{	
						baButtons[ i ] = ( byaButtons[ i ] != 0 );
						bAButtonWasPressed = ( bAButtonWasPressed || baButtons[ i ] );
					}

					//Now process the data
					if( (0 != (oMouseStateData.X | oMouseStateData.Y | oMouseStateData.Z) || bAButtonWasPressed == true ) && 
						( oMouseStateData.X > -1000 && oMouseStateData.X < 1000 ) &&
						( oMouseStateData.Y > -1000 && oMouseStateData.Y < 1000 ) )
					{
						if( m_bUseCLRMouseImput == false )
						{
							m_oMouseCursorLocation.X += oMouseStateData.X;
							m_oMouseCursorLocation.Y += oMouseStateData.Y;

							m_oMouseCursorLocation.X = Math.Max( m_oMouseCursorLocation.X,0 );
							m_oMouseCursorLocation.X = Math.Min( m_oMouseCursorLocation.X,m_oForm.ClientSize.Width );
							m_oMouseCursorLocation.Y = Math.Max( m_oMouseCursorLocation.Y,0 );
							m_oMouseCursorLocation.Y = Math.Min( m_oMouseCursorLocation.Y,m_oForm.ClientSize.Height );
						}
						else
						{
							//03/31/2005 Chris Hill  Where does 2 and 21 come from you might ask?  No friggin clue.
							//When I implimented this system it was not properly rspecting the mouses hot spot.  So I
							//manually figured out how much it was off.  Got me why, i'll worry about that later.  So
							//the 2 and 21 are what line up the click hot point withthe windows mouse.
							//04/01/2005 Chris Hill  We now support controls as the primary DX surface.  But in that case
							//we need to adjust our location some more.  
							m_oMouseCursorLocation = ConvertWinMousePointToOurMousePoint();
						}
						//04/02/2005 Chris Hill  If we are outside of our area then don't trigger events.
						if( m_oMouseCursorLocation.X >=  0 && m_oMouseCursorLocation.X <= this.Form.Width &&
							m_oMouseCursorLocation.Y >=  0 && m_oMouseCursorLocation.Y <= this.Form.Height )
						{
							//Did we move the mouse?
							if( oMouseStateData.X != 0 || oMouseStateData.Y != 0 )
							{
								MouseMoved( m_oMouseCursorLocation,oMouseStateData,baButtons );
							}

							if( 0 != (oMouseStateData.Z) )
							{
								MouseWheelMove( oMouseStateData.Z );
							}						

							if( m_baLastMouseButtonState == null )
							{
								m_baLastMouseButtonState = baButtons;
							}
							else
							{
								for( int i=0 ; i<baButtons.Length ; i++ )
								{
									if( baButtons[ i ] == true && m_baLastMouseButtonState[ i ] == false )
									{
										MouseDown( m_oMouseCursorLocation,i );
									}
									else if( baButtons[ i ] == false && m_baLastMouseButtonState[ i ] == true )
									{
										MouseUp( m_oMouseCursorLocation,i );
									}
								}
							}

							//Save the state so next time we know what happened this time.
							m_baLastMouseButtonState = baButtons;
						}	
					}
				}
				catch{}
			}
		}

		private void KeyboardEvent()
		{
			bool[] baState = null;


			while( m_oKBEventFire != null )
			{
				m_oKBEventFire.WaitOne(-1, false);

				if( m_oKBEventFire == null ){ continue; }

				try
				{
					m_oKeyboardDevice.Poll();
				}
				catch
				{
					continue;
				}

				if( m_oKBEventFire == null ){ continue; }

				//Ok now get the keyboard state
				GetKeyboardState( ref baState );

				//Do we have anything to compare to?  If not dont' do this
				if( m_baLastKeyboardState != null && baState != null )
				{
					//Now look for any keys that have changed
					for( Key oKey = Key.Escape; oKey <= Key.MediaSelect; oKey++ ) 
					{
						if( baState[ (int)oKey ] == true && m_baLastKeyboardState[ (int)oKey ] == false )
						{
							ManditoryKeyboardKeyDownProcessing( oKey,baState );
							KeyboardKeyDown( oKey,baState );
						}
						else if( baState[ (int)oKey ] == false && m_baLastKeyboardState[ (int)oKey ] == true )
						{
							KeyboardKeyUp( oKey,baState );
						}
					}
				}

				if( baState != null )
				{
					m_baLastKeyboardState = CopyKeyboardState( baState );
				}
			}
		}

				
		public bool[] GetMouseButtonState()
		{
			bool[] baState = new bool[ 3 ];

			baState[ 0 ] = m_baLastMouseButtonState[ 0 ];
			baState[ 1 ] = m_baLastMouseButtonState[ 1 ];
			baState[ 2 ] = m_baLastMouseButtonState[ 2 ];

			return( baState );
		}
		public bool GetKeyboardState( ref bool[] oState )
		{
			bool bRetVal = false;
			KeyboardState oKeyboardState;


			if( null == m_oKeyboardDevice ) 
			{
				throw new System.Exception( "Unable to retreive keyboard state, no keyboard device found." );
			}
			else
			{
				//If the app has lost focus then we can't get the keyboard...
				try
				{
					oKeyboardState = m_oKeyboardDevice.GetCurrentKeyboardState();
					oState = CopyKeyboardState( oKeyboardState );
					oKeyboardState = null;
					
					bRetVal = true;
				}
				catch
				{
					oState = null;
					bRetVal = false;
				}

				
				if( oState != null )
				{
					//Chris  I don't get it... an error is supposed to occur which we can trap if the foreground window
					//is no longer our window and we are in foreground mode.  So lets try a workaround...  It seems to be
					//returning that every key is pressed right now, so lets check for that.				
					bRetVal = PerformEmpericalKeyboardTest( oState );
					if( bRetVal == false )
					{
						m_oKeyboardDevice.Acquire();
						oKeyboardState = m_oKeyboardDevice.GetCurrentKeyboardState();
						oState = CopyKeyboardState( oKeyboardState );
						bRetVal = PerformEmpericalKeyboardTest( oState );

						if( bRetVal == false )
						{
							oState = null;
						}
					}
				}
			}

			return( bRetVal );
		}
		public string GetKeyboardTextList( bool[] oState )
		{
			string sRetVal = "";


			for( Key oKey = Key.Escape; oKey <= Key.MediaSelect; oKey++) 
			{
				if( oState[ (int)oKey ] == true )
				{
					if( sRetVal.Length > 0 )
					{
						sRetVal += ", ";
					}
					sRetVal += oKey.ToString();
				}
			}

			return( sRetVal );
		}
		//Chris  I don't get it... an error is supposed to occur which we can trap if the foreground window
		//is no longer our window and we are in foreground mode.  So lets try a workaround...  It seems to be
		//returning that every key is pressed right now, so lets check for that.				
		private bool PerformEmpericalKeyboardTest( bool[] oState )
		{
			long nNumThatAreTrue = 0;
			bool bRetVal = false;


			for( Key oKey = Key.Escape; oKey <= Key.MediaSelect; oKey++) 
			{
				if( oState[ (int)oKey ] == true )
				{
					nNumThatAreTrue++;
				}
			}
			
			//If they have 20 keys depressed they've got problems
			bRetVal = ( nNumThatAreTrue < 20 );

			return( bRetVal );
		}

		public bool[] CopyKeyboardState( KeyboardState oState )
		{
			bool[] oNewState = null;


			if( oState == null )
			{
				throw new System.Exception( "Keyboard state passed in was invalid." );
			}
			else
			{
				oNewState = new bool[ (int)Key.MediaSelect + 1 ];

				for( Key oKey = Key.Escape; oKey <= Key.MediaSelect; oKey++ ) 
				{
					oNewState[ (int)oKey ] = oState[ oKey ];
				}
			}

			return( oNewState );
		}
		public bool[] CopyKeyboardState( bool[] baState )
		{
			bool[] baNewState = null;


			if( baState == null )
			{
				throw new System.Exception( "Keyboard state passed in was invalid." );
			}
			else
			{
				baNewState = new bool[ (int)Key.MediaSelect+1 ];

				for( Key oKey = Key.Escape; oKey <= Key.MediaSelect; oKey++ ) 
				{
					baNewState[ (int)oKey ] = baState[ (int)oKey ];
				}
			}

			return( baNewState );
		}

		//08/09/2005 Chris Hill  This function converts the windows mouse point into our cooridnate system.
		private Vector2 ConvertWinMousePointToOurMousePoint()
		{
			Vector2 vRetVal;
			int nX = 3;
			int nY = 23;


			if( this.Form != this.TopmostForm )
			{
				vRetVal = new Vector2(	Control.MousePosition.X - this.TopmostForm.Left - this.Form.Left - nX,
										Control.MousePosition.Y - this.TopmostForm.Top - this.Form.Top - nY );
			}
			else
			{
				vRetVal = new Vector2(	Control.MousePosition.X - this.Form.Left - nX,
										Control.MousePosition.Y - this.Form.Top - nY );
			}

			if( this.TopmostForm.Menu != null )
			{
				vRetVal.Y -= 19;
			}

			return( vRetVal );
		}


		//Delegated Events
		public virtual bool MouseWheelMove( long nDirection )
		{
			if( m_odDelegate_MouseWheelMove != null )
			{
				m_odDelegate_MouseWheelMove( nDirection );
			}

			return( false );
		}

		public virtual bool MouseMoved( Vector2 vCurPos,MouseState oMouseStateData,bool[] baButtons )
		{
			if( m_odDelegate_MouseMoved != null )
			{
				m_odDelegate_MouseMoved( m_oMouseCursorLocation,oMouseStateData,baButtons );
			}

			return( false );
		}

		public virtual bool MouseUp( Vector2 vCurPos,long nButton )
		{
			if( m_odDelegate_MouseUp != null )
			{
				m_odDelegate_MouseUp( vCurPos,nButton );
			}

			return( false );
		}
		public virtual bool MouseDown( Vector2 vCurPos,long nButton )
		{
			if( m_odDelegate_MouseDown != null )
			{
				m_odDelegate_MouseDown( vCurPos,nButton );
			}
		
			return( false );
		}

		private void ManditoryKeyboardKeyDownProcessing( Key oKey,bool[] oState )
		{
			if( oKey == Microsoft.DirectX.DirectInput.Key.Numlock )
			{
				m_bNumLockToggled = !m_bNumLockToggled;
			}
			else if( oKey == Microsoft.DirectX.DirectInput.Key.CapsLock )
			{
				m_bCapsLockToggled = !m_bCapsLockToggled;
			}
		}
		public virtual bool KeyboardKeyDown( Key oKey,bool[] oState )
		{
			if( m_odDelegate_KeyboardKeyDown != null )
			{
				m_odDelegate_KeyboardKeyDown( oKey,oState );
			}

			return( false );
		}
		public virtual bool KeyboardKeyUp( Key oKey,bool[] oState )
		{
			if( m_odDelegate_KeyboardKeyUp != null )
			{
				m_odDelegate_KeyboardKeyUp( oKey,oState );
			}

			return( false );
		}

		public virtual void Error( System.Exception oError )
		{
			if( m_odDelegate_Error == null )
			{
				DSMisc.ShowErrors( oError );
			}
			else
			{
				m_odDelegate_Error( oError );
			}
		}


		#region Delegate Registration Functions
		//These methods register the callback function the user of the class wishes.  
		public void RegisterDelegate_MouseUp( CallbackMouseUp odMouseUp )
		{
			m_odDelegate_MouseUp += odMouseUp;
		}
		public void RegisterDelegate_MouseDown( CallbackMouseDown odMouseDown )
		{
			m_odDelegate_MouseDown += odMouseDown;
		}
		public void RegisterDelegate_MouseWheelMove( CallbackMouseWheelMove odMouseWheelMove )
		{
			m_odDelegate_MouseWheelMove += odMouseWheelMove;
		}
		public void RegisterDelegate_MouseMoved( CallbackMouseMoved odMouseMoved )
		{
			m_odDelegate_MouseMoved += odMouseMoved;
		}
		public void RegisterDelegate_KeyboardKeyDown( CallbackKeyboardKeyDown odKeyboardKeyDown )
		{
			m_odDelegate_KeyboardKeyDown += odKeyboardKeyDown;
		}
		public void RegisterDelegate_KeyboardKeyUp( CallbackKeyboardKeyUp odKeyboardKeyUp )
		{
			m_odDelegate_KeyboardKeyUp += odKeyboardKeyUp;
		}
		public void RegisterDelegate_Error( CallbackError odError )
		{
			m_odDelegate_Error += odError;
		}
		#endregion
	

		#region Properties
		public bool MouseInExclusiveMode
		{
			get
			{
				return( m_bMouseInExclusiveMode );
			}
			set
			{
				if( m_oMouseDevice == null )
				{
					m_bMouseInExclusiveMode = value;
				}
				else if( m_bMouseInExclusiveMode != value )
				{
					m_bMouseInExclusiveMode = value;
					m_oMouseDevice.Unacquire(); 
					InitMouse();
				}
			}
		}
		public System.Windows.Forms.Control Form
		{
			get
			{
				return( m_oForm );
			}
		}
		public System.Windows.Forms.Form TopmostForm
		{
			get
			{
				System.Windows.Forms.Control oLoopObj = this.Form;


				if( m_oTopmostForm == null )
				{
					if( this.Form.Parent != null )
					{
						//Loop until we get to the topmost parent... which has to be the form
						oLoopObj = this.Form.Parent;
						while( oLoopObj.GetType().BaseType.ToString() != "System.Windows.Forms.Form" )
						{
							oLoopObj = oLoopObj.Parent;
						}
					}

					m_oTopmostForm = (System.Windows.Forms.Form)oLoopObj;
				}

				return( m_oTopmostForm );
			}
		}
		public Vector2 MouseCursor
		{
			get
			{
				return( m_oMouseCursorLocation );
			}
			set
			{
				m_oMouseCursorLocation = value;
			}
		}
		public bool[] MouseButtonState
		{
			get
			{
				return( GetMouseButtonState() );
			}
		}

		//12/08/2004 Chris Hill  Added a debug mode for tracking.
		public bool DebugMode
		{
			set
			{
				//Are we turning it on when it was off?
				if( m_bDebugMode == false && value == true )
				{
					//Only make a new log file name if we don't have one already
					if( m_sDebugPath.Length == 0 )
					{
						m_sDebugPath =	DSMisc.GetDevelopmentAppPath() + 
							"DSInputWrapper_DebugFile_" + 
							DateTime.Now.ToString( "yyyy-MM-dd hh" ) + "h" + 
							DateTime.Now.ToString( "mm" ) + "m" + 
							DateTime.Now.ToString( "ss" ) + "s" + 
							".OUT";

						//Then write a header
						DSMisc.WriteToDebugFile( m_sDebugPath,value,false,0,
							"\r\n\r\nStarting Debug Log File For DSInputWrapper\r\n" +
							"--------------------------------------------" );
					}
				}
					//Are we turning it off when it was currently on?  Then clear the path.
				else if( m_bDebugMode == true && value == false )
				{
					m_sDebugPath = "";
				}

				m_bDebugMode = value;
			}
			get
			{
				return( m_bDebugMode );
			}
		}
		public string DebugPath
		{
			get
			{
				return( m_sDebugPath );
			}
			set
			{
				m_sDebugPath = value;

				//We turn off then on the debug mode so that it writes a new header to the log
				if( m_bDebugMode == true )
				{
					DebugMode = false;
					DebugMode = true;
				}				
			}
		}
		//12/28/2004 Chris Hill  This handy function isn't used right now but took a long time to write so 
		//I wanted it recorded somewhere.
		public bool MouseAquired
		{
			get
			{
				Microsoft.DirectX.DirectInput.MouseState oState;
				bool bMouseAquired = false;

				try
				{
					oState =  m_oMouseDevice.CurrentMouseState; 
					bMouseAquired = true;
				}
				catch{}

				return( bMouseAquired );
			}
		}
		public bool UseAbsoluteMouseCoordinates
		{
			get
			{
				return( m_bUseCLRMouseImput );
			}
			set
			{
				m_bUseCLRMouseImput = value;
			}
		}
		public bool CapsLockToggled
		{
			get
			{
				return( m_bCapsLockToggled );
			}
		}
		public bool NumLockToggled
		{
			get
			{
				return( m_bNumLockToggled );
			}
		}
		#endregion
	}
}
