// Walk and kick: Game variables
// Author: Philipp Allgeuer <pallgeuer@ais.uni-bonn.de>
 
 // Ensure header is only included once
#ifndef WAK_GAME_VARS_H
#define WAK_GAME_VARS_H

// Includes
#include <walk_and_kick/wak_common.h>

// Walk and kick namespace
namespace walk_and_kick
{
	/**
	* @class GameVars
	* 
	* @brief An interface class for encapsulating all of the data that the walk and kick game states should command.
	* 
	* This class is generated by WAKGameState and its derived classes, and used by WAKBehState and its derived classes.
	**/
	class GameVars
	{
	public:
		// Ball target type enumeration
		enum BTType           // Ball target type
		{
			BTT_UNKNOWN = 0,  // Unknown source of ball target
			BTT_GOAL,         // Ball target based on goal detection
			BTT_POSE,         // Ball target based on localised robot pose
			BTT_COMPASS,      // Ball target based on compass heading
			BTT_COUNT
		};
		static bool ballTargetTypeValid(int type) { return (type > BTT_UNKNOWN && type < BTT_COUNT); }
		static bool ballTargetTypeValid(BTType type) { return ballTargetTypeValid((int) type); }
		static char ballTargetTypeChar(BTType type) { if(ballTargetTypeValid(type)) return BallTargetTypeChar[type]; else return BallTargetTypeChar[BTT_UNKNOWN]; }
		static const std::string& ballTargetTypeName(BTType type) { if(ballTargetTypeValid(type)) return BallTargetTypeName[type]; else return BallTargetTypeName[BTT_UNKNOWN]; }
	private:
		static const char BallTargetTypeChar[BTT_COUNT];
		static const std::string BallTargetTypeName[BTT_COUNT];

	public:
		// Foot selection enumeration
		enum FootSelection
		{
			FS_LEFT_FOOT = -1,   // Suggest use of the left foot
			FS_EITHER_FOOT = 0,  // No particular reason to prefer either foot
			FS_RIGHT_FOOT = 1    // Suggest use of the right foot
		};
		static const std::string& footSelectionName(FootSelection foot) { if(foot < 0) return FootSelectionName[0]; else if(foot > 0) return FootSelectionName[2]; else return FootSelectionName[1]; }
	private:
		static const std::string FootSelectionName[3];

	public:
		// Constructor
		GameVars() { reset(); }

		// Reset function
		void reset();

		// Validation function
		bool coerceEnums();

		// Get functions
		char ballTargetTypeChar() const { return ballTargetTypeChar(ballTargetType); }
		const std::string& ballTargetTypeName() const { return ballTargetTypeName(ballTargetType); }
		bool suggestLeftFoot() const { return (suggestFoot < 0); }
		bool suggestRightFoot() const { return (suggestFoot > 0); }
		bool noSuggestedFoot() const { return (suggestFoot == 0); }

		// Member variables
		int forceBehStateByID;        // Force a particular behaviour state, specified by its behaviour state ID
		FootSelection suggestFoot;    // Strongly suggest the use of a particular foot
		bool dribbleIfPossible;       // Dribble the ball towards the ball target if this is possible
		bool kickIfPossible;          // Kick the ball towards the ball target if this is possible
		DiveDirection diveIfPossible; // Dive to save the ball if this is possible
		float ballTargetConf;         // Confidence of the ball target
		Vec2f ballTargetDir;          // Egocentric vector from the robot to the ball target
		float ballTargetWedge;        // The width of the ball target expressed as the angle it subtends at the ball position
		BTType ballTargetType;        // Enumeration value specifying the type of ball target that was calculated
		Vec3f targetPose;             // The target walking pose for the robot
		float targetPoseTol;          // The tolerance in the specified target pose
		bool targetPoseValid;         // Boolean flag whether the target pose is valid
	};
}

#endif
// EOF