/**
 * \file CoachKernel.h
 * \date 07.12.2002
 * \author Peter Trebaticky
 *
 * Interface for the CoachKernel class
 */

#ifndef MODULES_COACHKERNEL_H
#define MODULES_COACHKERNEL_H

#include "Coach/CoachAnalyser.h"
#include "Player/Formation.h"

#include "Coach/Interfaces/CoachMemory.h"
#include "Coach/Interfaces/CoachSynchronization.h"
#include "Common/Protocol/CommandGen.h"
#include "Common/Tasks.h"
#include "Common/Module.h"
#include "Common/Main.h"
#include "Common/Support/Debug.h"

// How many times should we try to send leam graphic?
#define TEAM_GRAPHIC_MAX_TRIES 20

/// How many CLang messages to store in FIFO buffer
#define FIFO_BUFFER_SIZE 10
#define MAX_CLANG_STR_LEN 8154
/// How many pass lengths we distinguish
#define PASS_LEN_COUNT 3
/// Various pass lengths ( 0 <= passLens[0] <= passLens[1] ... > )
const float passLens[PASS_LEN_COUNT] = {5.0f, 10.0f, 20.0f};

#define NUM_FORMATIONS 6
enum {
	FORMATION622 = 0,
	FORMATION532,
	FORMATION433,
	FORMATION523,
	FORMATION343,
	FORMATION334
};

const struct FORMATION {
	int defs, mids, atts;
	char name[7];
} formation[NUM_FORMATIONS] = {
	{6, 2, 2, "622"},
	{5, 3, 2, "532"},
	{4, 3, 3, "433"},
	{5, 2, 3, "523"},
	{3, 4, 3, "343"},
	{3, 3, 4, "334"}
};

#define NUM_ZONES 5
const struct ZONE {
  float from, to;
} zones[NUM_ZONES] = {
  {-52.5f, -36.0f},
  {-36.0f, -15.0f},
  {-15.0f,  15.0f},
  { 15.0f,  36.0f}, 
  { 36.0f,  52.5f}
};


/// Player's distance from ball in x, when he is considered to be midfielder
const float DIST_X_MID_FIELDER = 15.;

/// Statistics we trace for players
struct PLAYER_STATISTICS
{
	int shootsOnGoal;         ///< number of shoots on goal
	float sumLenShootsOnGoal; ///< sum of lengths of shoots on goal
	int passesAll[PASS_LEN_COUNT + 1];     ///< number of all passes for all lengths
	int passesSuccess[PASS_LEN_COUNT + 1]; ///< number of successful passes for all lenghts
	float sumPassSucLen;///< sum of length of successful passes
	int passesReceived; ///< number of received passes
	int interceptions;  ///< number of intercepted passes
	int cyclesWithBall; ///< number of cycles when player has ball in kickable area
	Vector sumDistFromBall; ///< sum of distances from ball till current cycle in x and y
	float sumSpeedNearBall; ///< sum of speed when near ball
	int cyclesNearBall;     ///< number of cycles near ball
	int cyclesAttacker;     ///< how many cycles we considered him to be attacker 
	int cyclesDefender;     ///< how many cycles we considered him to be defender
	int cyclesMidfielder;   ///< how many cycles we considered him to be midfielder 
};

/// What does "ball is near" mean in meters
const float BALL_NEAR_DIST = 3.0f;

/// What is the minimal required speed of ball on goal line 
/// (in order to detect shoot on goal)
const float SPEED_ON_GOAL_LINE_MIN = 0.1f;

/// Statistics we trace for ball
struct BALL_STATISTICS
{
	int cyclesOnOurHalf;   ///< how many cycles was ball on our half
	int cyclesOnTheirHalf; ///< how many cycles was ball on their half
  int cyclesInZone[NUM_ZONES]; ///< how many cycles was ball in which zone
};

/// Who kicked the ball, when, and where it was
struct KICK_INFO
{
	int who;        ///< 0: none, 1 - 11: our player, 2 - 22: their player
	int when;       ///< in which cycle was ball kicked
	Point from; ///< where it was kicked
};

/**
 * \class CoachKernel
 * \author Peter Trebaticky
 * \brief CoachKernel module
 *
 * Coach kernel (all in one)
 * synchronization, world model, simulation parameters
 */

class CoachKernel : public Module, public CoachMemoryInterface,
	public CoachSynchronizationInterface
{
public:
	// ZMENA 10.04.2005
	void MakePlayerSelection();
	float CalcRealSpeedMax(int type);
	virtual void Run(int iTask = -1);
	//
// Construction and destruction
	CoachKernel(
		const char* name = "CoachKernel",
		const char* desc = "CoachKernel module");
	virtual ~CoachKernel();

// Interface implementation
	virtual int Init(int argc, char **argv, int iTask = -1);

	virtual Interface* GetInterface(int task) const;

	/// Coach memory
	//@{
	virtual int GetSimTime() const { return simTime; }
	virtual PlayMode GetPlayMode() const { return playMode; }

	virtual unsigned GetOurScore() const { return scoreOur; }
	virtual unsigned GetTheirScore() const { return scoreTheir; }

	virtual int GetTypeByNumber(unsigned number) const { return playerTypesByNumber[number]; }
	//@}

	/// Simulation parameters
	//@{
	virtual void OnServerParam(const SERVER_PARAMS* params);
	virtual void OnPlayerParam(const PLAYER_PARAMS* params);
	virtual void OnPlayerType(int id, const PLAYER_TYPE* type);
	//@}

	/// Perceptions and world model
	//@{
	virtual void OnInit(bool side);
	virtual void OnChangeMode(int time, PlayMode mode);
	virtual void OnHear(int time, bool our, int uniformNumber, const char* message);
	virtual void OnScore(int time, unsigned int our, unsigned int their);
	virtual void OnSeeGlobal(const COACH_VISUAL_INFO* vi);
	virtual void OnChangePlayerType(unsigned number, int type);
	virtual void OnGoal(bool p_WeGaveTheGoal);
	//@}

	/// Handler for 'ok team_graphic' messages
	virtual void OnOkTeamGraphic(int x, int y);

protected:
	/// Returns index according to length
	int GetLengthIndex(float dist)
	{
		static int i;
		for(i = 0; i < PASS_LEN_COUNT; i++) if(dist <= passLens[i]) return i;
		return i;
	}

	/// Returns expected formation of team
	/// \param our true - our formation
	int GetFormation(bool our);

	int playerTypesByNumber[12];///< Player types according to their number (1 - 11)
	int simTime;				///< Simulation time
	PlayMode playMode;			///< Play mode

	int timeInPlayOn;           ///< How many cycles was play on mode

// ********************** ANALYZA *********************
	CoachAnalyser analyser;
	Formation formations;
// ********************** ANALYZA *********************

	int scoreOur;			///< Our score
	int scoreTheir;		///< Opponents' score

	bool ourSide;               ///< true: left side, false: right side

	/// Server parameters information
	/// \warning may be NULL if not available
	SERVER_PARAMS* serverParams;
	
	/// Hetero players information
	/// \warning may be NULL if not available
	PLAYER_PARAMS* playerParams;
	
	/// Player type information
	/// \warning may be NULL if not available
	PLAYER_TYPE* playerTypes;

	/// Last VI arrival time
	int timeOfLastVisualInfo;

	/// Last information about ball
	COACH_BALL lastBallInfo;

	/// Player that was nearest to the ball in previous cycle
	/// when kick is detected we assume that this player has kicked the ball
	/// 0: none, 1 - 11: our player, 12 - 22: their player (number minus 11)
	int lastNearestPlayer; 

	/// To detect pass - when the ball was kicked, by whom, and from where
	KICK_INFO lastKick;

	/// Is simulation time running?
	bool IsTimeStoped() const;

	/// It fills FIFO buffer and sends the first message when possible
	/// When the FIFO buffer is full, the first message is replaced
	/// If msg is NULL, it just tries to send the first message (if any)
	void SayMessage(const char* msg);
	char FIFObuffer[FIFO_BUFFER_SIZE + 1][MAX_CLANG_STR_LEN];
	int FIFObottom, FIFOtop;

	/// If it is possible to send message due to limitations of communication
	///   returns > 0
	/// else returns 0 
	int CanSendMessage();

	int continousTimeInPlayOn;  ///< How many consequent cycles was play on mode 
	int canSendCLmessage;       ///< If == 0, we can send CLang message (we use just define messages)
	int sayCoachCnt;            ///< How many freeform messages we sent

	/// MH: Send logo to server
	bool SendTeamGraphic(const char* path);

	char teamGraphicDir[512];

	/// Which parts of logo were already sent?
	bool teamGraphicOk[32][8];
	int teamGraphicOkCount;
	int teamGraphicTries;

private:
	//!!!!!!!!! Gridders ad !!!!!!!!!!!!!		
	int playerChange[4];
	//!!!!!!!!! Gridders ad !!!!!!!!!!!!!
	
	/// Command generator
	CommandGen* commandGen;

	/// Flag coordinates
	Point flagPos[56];

	/// Statistics for our players 1 - 11
	PLAYER_STATISTICS statsOurPlayer[12];

	/// Statistics for their players 1 - 11
	PLAYER_STATISTICS statsTheirPlayer[12];

	BALL_STATISTICS statsBall;	///< Ball

	int advice; 
	
	int nHeteroCounter;

	int nZmenaTypov;

//	/// Synchronization
//	const SENSE_BODY* m_pLastSB;
//	const VISUAL_INFO* m_pLastVI;
//	bool m_bDecisionWasMade;

//	/// Synchronization mode
//	//@{
//	SynchroMode m_iSynchMode;
//	SynchroMode m_iNextSynchMode;
//	//@}

};

#endif // MODULES_COACHKERNEL_H
