/*****************************************************************************
 * $Id: joystick.hh,v 1.49 2006/08/03 02:17:21 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Joystick (OS-neutral).
 * @verbatim
 * ---------------------------------------------------------------------------
 *
 * Purpose:
 * --------
 *
 * This Joystick class abstract differences in joystick drivers on different
 * operating systems.  An application can use the Joystick class for OS-neutrality.
 *
 * Axis values:
 * ------------
 *
 * Axis values are returned in range -32767...+32767 as:
 *
 *           -32767
 *              |
 *    -32767  --o--  +3267
 *              |
 *           -32767
 *
 * .fast/.slow refer to joystick axis #3 (typically for throttle control).
 *
 * Calibration:
 * ------------
 *
 * The Joystick class provides .mCalibration members and Calibrate() methods
 * for storing and changing joystick calibration values.  These values are
 * intended entirely for the application (the Joystick class doesn't use them).
 * For example, if joy.mCalibration.mLeft.mLo equals 10121, and the joystick is
 * moved to center, say the event equals 2012, the Joystick class code will
 * still report the event even though the movement is at the joystick's deadzone.
 * The application is responsible for looking at joy.mCalibration.mLeft.mLo
 * and determining that no response is needed by that joystick event.
 *
 * -----------------------------------------------------------------------------
 * @endverbatim
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#ifndef GFXINPUT_JOYSTICK_HH
#define GFXINPUT_JOYSTICK_HH 1

#if defined(_WIN32)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <windef.h>
#include <Mmsystem.h>
#elif defined(linux)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/joystick.h>
#endif

#include "gfx_cc.hh"
#include "gfx_os.hh"
#include "gfx_funcs.hh"

// -----------------------------------------------------------------------------
namespace gfxInput {

// Joystick axis extremes.
const int JOY_LO = 8000;	///< JOY_LO can be changed
const int JOY_HI = 32767;	///< DON'T CHANGE!! joystick_win32.cc depends on JOY_HI=32767

/// Which joystick axis.
enum eJoyAxis
{
	eJoyAxis_NONE,
	eJoyAxis_LEFTRIGHT,
	eJoyAxis_UPDOWN,
	eJoyAxis_THIRD,
};

/// Which joystick button.
enum eJoyButton
{
	eJoyButton_NONE,
	eJoyButton_1,
	eJoyButton_2,
	eJoyButton_3,
	eJoyButton_4,
	eJoyButton_LAST = eJoyButton_4
};


////////////////////////////////////////////////////////////////////////////////
/// @brief Joystick event class
class JoyEvent
{
public:
				JoyEvent( void ) { Clear(); }
	void		Clear( void ) { mAxis   = eJoyAxis_NONE;   mAxisVal = 0;
                                mButton = eJoyButton_NONE; mButtonVal = 0; }
	// axis event:
	eJoyAxis	mAxis;			///< which axis
	int			mAxisVal;		///< axis movement

	// button event:
	// no    button = eJoyButton_NONE
	// first button = 1 (and so on)
	eJoyButton	mButton;		///< which button
	bool		mButtonVal;		///< button on/off

friend class Joystick;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief OS-neutral joystick class.
class Joystick
{
				PREVENT_COPYING(Joystick)
public:
				Joystick( void );
	bool		Enable( bool flag );	///< enable/disable joystick, returns true if present/enabled
	bool		IfEnabled( void ) { return mEnabled; }
	bool		PollEvent( void );		///< poll next joystick event(s)
	bool		CalibrateDefault( void );
	bool		CalibrateMin( int left, int right,
                              int up,   int down,
                              int slow, int fast ); ///< throttle analogy
	bool		CalibrateMax( int left, int right,
                              int up,   int down,
                              int slow, int fast ); ///< throttle analogy
	bool		CalibrateDeadzone( const int dz[3] );
	bool		CalibrateDirection( const int d[3] );

protected:
	bool		Open( void );
	void		Close( void );
	void		ClearEvent( void );
	void		CheckJoyvalMin( int* val );
	void		CheckJoyvalMax( int* val );

// joystick state
protected:
	bool		mEnabled;
public:
	JoyEvent	mEvent;		///< axis and/or button event

// axis calibration
public:
	int		mAxisDir[3];
	struct
	{
		struct { int mLo; int mHi; } mLeft;
		struct { int mLo; int mHi; } mRight;
		struct { int mLo; int mHi; } mUp;
		struct { int mLo; int mHi; } mDown;
		struct { int mLo; int mHi; } mSlow; ///< third axis (throttle analogy)
		struct { int mLo; int mHi; } mFast;
	} mCalibration;
};

} // namespace gfxInput
// -----------------------------------------------------------------------------

#endif // GFXINPUT_JOYSTICK_HH
