/*****************************************************************************
 * $Id: input_queue.cc,v 1.16 2006/10/10 04:14:55 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Input event queue.
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#define GFXINPUT_INPUT_QUEUE_CC 1
#include "gfx.hh"
#include "gfx_gfxsys.hh"
using namespace gfx;
#include "input_queue.hh"
#if GFXSYS_OPENGL
#include "keyboard_opengl.hh"
#endif

namespace gfxInput {

// These support default ctor constructing an interim NOP queue.
SafePtr<InputQueue> InputQueue::msInputQueue;   // pointer
InputQueue      InputQueue::msDummyInputQueue;  // actual object by default ctor
Joystick        InputQueue::msDummyJoystick;    // actual object
int             InputQueue::msInstanceCnt;

/*****************************************************************************
 * Default ctor creates an empty NOP queue, suited for a construction at load-time.
 * When Engine is ready, it should call InputQueue::Enable() to activate a real queue.
 *****************************************************************************/
InputQueue::InputQueue( void )
{
	msInputQueue = &msDummyInputQueue;
	mJoy		 = &msDummyJoystick;

    // Two instances: a dummy and a real one.
    DEBUG_CODE( ++msInstanceCnt; ASSERT( msInstanceCnt <= 2 ); )
}

/*****************************************************************************
 * This class isn't exactly a singleton: it first has a dummy queue
*  which is replaced by a real queue once the program is ready.
 *****************************************************************************/
SafePtr<InputQueue>
InputQueue::GetInstance( void )
{
    // msInputQueue initially is msDummyInputQueue, reassigned by Enable().
    return msInputQueue;
}

/*****************************************************************************
 * Enable the input queue.
 * This should be called after the gfxsys (eg OpenGL/GLUT) is ready.
 *****************************************************************************/
void
InputQueue::Enable( SafePtr<Joystick> joy )
{
	msInputQueue = this;  // "this" would be a class member (Engine::mInputQueue).
	mJoy		 = joy;
    GfxsysEnableKeyboard();
}

/*****************************************************************************
 * Dequeue the next keyboard event.
 * @return False if no more keyboard events.
 *****************************************************************************/
bool
InputQueue::GetKeyEvent( KeyEvent* event/*OUT*/ )
{
	if ( mKeyQueue.size() )
	{
		*event = mKeyQueue.front();
		mKeyQueue.pop();
		return true;
	}
	else
		return false;
}

/*****************************************************************************
 * Dequeue the next joystick event.
 * @return False if no more joystick events.
 *****************************************************************************/
bool
InputQueue::GetJoyEvent( JoyEvent* event/*OUT*/ )
{
	if ( mJoyQueue.size() )
	{
		*event = mJoyQueue.front();
		mJoyQueue.pop();
		return true;
	}
	else
		return false;
}

/*****************************************************************************
 * @return Amount of events in keyboard queue.
 *****************************************************************************/
int
InputQueue::KeyEvents( void )
{
	return mKeyQueue.size();
}

/*****************************************************************************
 * @return Amount of events in joystick queue.
 *****************************************************************************/
int
InputQueue::JoyEvents( void )
{
	return mJoyQueue.size();
}

/*****************************************************************************
 * Driven by a timer tick to poll input devices.
 * Must be called by the application's timer handler (to feed the queue).
 * @param	milsec
 *			The amount of time since the last timer interrupt.
 *****************************************************************************/
void
InputQueue::Tick( int milsec )
{
	if ( mJoy->IfEnabled() && mJoy->PollEvent() )
		mJoyQueue.push( mJoy->mEvent );
}

/*****************************************************************************
 * Enqueue a keyboard event.
 *****************************************************************************/
void
InputQueue::PutKeyEvent( int key, bool special, bool press, bool shift, bool ctrl, bool alt )
{
	KeyEvent event( key, special, press, shift, ctrl, alt );
	mKeyQueue.push( event );
}

} // namespace gfxInput
