//!
/**
 **************************************************************************************************************************************************************
 * BotGB implementation
 **************************************************************************************************************************************************************
 * @file   BotGB.h
 * @author Guillaume Blanchard
 **************************************************************************************************************************************************************/
#pragma once

/**************************************************************************************************************************************************************
 * Includes
 **************************************************************************************************************************************************************/

// std
#include <vector>

// BotStrike
#include "BotStrike.h"
#include "AStar.h"

/**************************************************************************************************************************************************************
 * Namespace
 **************************************************************************************************************************************************************/

namespace BS {

/**
 * Bot information structure
 */
struct CBotInfo
{
    int             x;
    int             y;
    int             dx;
    int             dy;

	CBotInfo() {}
	CBotInfo(int x0, int y0): x(x0), y(y0) {}
};

/**
 * The BotGB class implementation.
 */
class CBotGB
{
public: // member constantes and enumerations

	/// Bot states enumeration
	enum STATE
	{
		STATE_DEFAULT, ///< The BotTest from Cyanide
		STATE_NINJA,   ///< Go close to the foe and make it fall into a trap
		STATE_BERSERK, ///< Fire in the hole!
		STATE_SEARCH,  ///< Search & destroy
		STATE_SCOUT,   ///< Patrol and attack encounter
	};

public: // member variables

	CBotInfo            own;               ///< Own coordinate information
	ETeam::Type         own_team;          ///< Own team
	int                 friend_num;        ///< Friends number
	int					ennemy_num;        ///< Ennemies number
	CBotInfo            ennemy;            ///< Ennemy coordinate information
	ETeam::Type         ennemy_team;       ///< Ennemy team
	int                 ennemy_move;       ///< Ennemy orientation
    int                 ennemy_stopped;    ///< Count the number of turns while the ennemy is immobile
    int                 grenades;          ///< Number of grenade currently brought by the bot
    int                 grenades_area;     ///< The range of grenade explosion
    int                 grenades_per_bots; ///< The number of grenades needed to kill a bot
	STATE               state;             ///< The current bot's state. @see BS::CBotGB::STATE
	int                 fire_counter;      ///< Berserk fire counter
	std::vector<CNode*> path;              ///< The last path (rebuild only when ennemy is moving)
	std::vector<int>    free_cells;        ///< List of free cells into the arena (to optimize full search)

    BS::CMessage&       msg;               ///< The last message data

public: // member methods

	// Cosntruct the bot class
	CBotGB(BS::CMessage& msg0);

	// Tell if a given is valid (ie. into the grid)
	BOOL IsValidCell(i32 x0, i32 y0) const;

	// Tell if a given is passable
	BOOL IsPassable(i32 x0, i32 y0) const;

	// Compute the free cells list (the cells where there is no wall).
	i32 ComputeFreeCells();

	// Find an ennemy.
	BOOL FindEnemy();

	// Compute the number of bot in each team.
	i32 ComputeTeamNumber();

	// Tell if the bot can move in a given direction
    BOOL CanMove(int dx0, int dy0) const;

	// Tell if the bot can move the adjacent cell
    BOOL CanLook(int dx0, int dy0) const;

	// Check for ennemy in a given direction and shoot him if possible
	BOOL RotateAndShoot(int dx0, int dy0);

	// Check for ennemy in a given direction
    BOOL CanSee(int dx0, int dy0, int& distance) const;

	// Check for ennemy in a given direction
    BOOL CanSeeFrom(int x0, int y0, int dx0, int dy0, int& distance) const;

	// Check if bot can shoot an ennemy.
    BOOL CanShoot(int& distance) const;

	// Check if bot can trough a grenade.
	BOOL CanGrenade() const;

	// Check if 2 bots are aligned.
	BOOL AreAligned(const CBotInfo& b1, const CBotInfo& b2, i32& dx0, i32& dy0) const;

	// Check bot can attack an ennemy.
	BOOL CheckAttack();

	// Convert dx/dy to orientation index (0~8)
	i32 DeltaToRotation(i32 dx, i32 dy) const;

	//
	//void RotationToDelta(i32 rot, i32& dx, i32& dy) const

private:

	/// Make the copy operator private to prevent bot copy
    CBotGB& operator = (const CBotGB&) { return *this; }

};

/**************************************************************************************************************************************************************
 * Namespace
 **************************************************************************************************************************************************************/

}