
#pragma once
#ifndef AI_BEHAVIOR_HPP
#define AI_BEHAVIOR_HPP

#include "AI_Fuzzy.hpp"
#include "AI_FireStyle.hpp"



namespace MW4AI
{
	class TacticInterface;

	namespace Behaviors
	{

		class Behavior
		{
		  public:
			virtual Fuzzy Execute(TacticInterface& i) = 0;

			Behavior();
			virtual ~Behavior();

			bool IsHappy() const
			{
				return (m_Happy);
			}

			virtual bool ShouldStopImmediately() const;

		  protected:
			void SetHappy(bool happy)
			{
				m_Happy = happy;
			}

		  private:
			bool m_Happy;
		};

		class TryToFire
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			TryToFire(FireStyles::FireStyleID style = FireStyles::FIRE_MAXIMUM, Stuff::Scalar multiplier = 1);

		  private:
			const FireStyles::FireStyleID m_FireStyle;
			const Stuff::Scalar m_Multiplier;
		};

		class EvasiveManeuvers
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			EvasiveManeuvers();

		  protected:
			virtual bool OKtoCrouch(TacticInterface& i) const { return (false); }

		  private:
			Stuff::Scalar m_LastForceDestinationRecalc;
		};

		class EvasiveBehavior
			: public EvasiveManeuvers
		{
		  public:
			Fuzzy Execute(TacticInterface& i);
		};

		class JumpToAvoidCollision
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			JumpToAvoidCollision(Stuff::Scalar time = 1.5f, Stuff::Scalar radius = 10);

		  private:
			const Stuff::Scalar m_Time;
			const Stuff::Scalar m_Radius;
		};

		class AvoidTrafficJams
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);
		
			AvoidTrafficJams();
			
		  private:
			Stuff::Scalar m_LastTrafficJam;
		};

		class DodgeIfLineOfFireBlocked
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);
		};

		class DefensiveBehavior
			: public EvasiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			JumpToAvoidCollision m_JumpToAvoidCollision;
			AvoidTrafficJams m_AvoidTrafficJams;
		};

		class AggressiveBehavior
			: public DefensiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			DodgeIfLineOfFireBlocked m_DodgeIfLineOfFireBlocked;
		};

		class StopAndFire
			: public AggressiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  protected:
			bool OKtoCrouch(TacticInterface& i) const;

		  private:
			TryToFire m_Fire;
		};

		class Ram
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
		};

		class Joust
			: public DefensiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			Joust();

		  private:
			TryToFire m_Fire;

		    enum Mode
			{
				HEADING_IN,
				HEADING_OUT
			};
			Mode m_Mode;
		};

		class Rush
			: public AggressiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
		};

		class HitAndRun
			: public AggressiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			HitAndRun();

		  private:
		    enum Mode
			{
				HEADING_IN,
				HEADING_OUT
			};

			Mode m_Mode;
			TryToFire m_Fire;
		};

		class Rear
			: public AggressiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
		};

		class Front
			: public AggressiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
		};

		class CircleOfDeath
			: public DefensiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
		};

		class Retreat
			: public EvasiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			Retreat();

		  private:
			JumpToAvoidCollision m_Jump;
			AvoidTrafficJams m_AvoidTrafficJams;
		};

		class BackUpAndFire
			: public DefensiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
			AvoidTrafficJams m_AvoidTrafficJams;
		};

		class CircleHover
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
		};

		class Strafe
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			Strafe();

		  private:
			enum Mode
			{
				HEADING_IN,
				HEADING_OUT
			};

			Mode m_Mode;
		};

		class StandGround
			: public DefensiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  protected:
			bool OKtoCrouch(TacticInterface& i) const { return (true); }

		  private:
			TryToFire m_Fire;
		};

		class JumpAndShoot
			: public Behavior
		{
		  public:
			JumpAndShoot();

			Fuzzy Execute(TacticInterface& i);

			bool ShouldStopImmediately() const;

		  private:
			bool m_SeenByTarget;

			enum JumpMode
			{
				JUMPING,
				WAITING
			};
			JumpMode m_JumpMode;
			Stuff::Scalar m_HoverHeight;
		};

		class Snipe
			: public DefensiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

			Snipe();

		  private:
			TryToFire m_Fire;

			enum Mode
			{
				HEADING_IN,
				HEADING_OUT
			};

			Mode m_Mode;
		};

		class Defend
			: public EvasiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			AvoidTrafficJams m_AvoidTrafficJams;
		};

		class ShootOnly
			: public TryToFire
		{
		};

		class LocalPatrol
			: public DefensiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  protected:
			bool OKtoCrouch(TacticInterface& i) const { return (true); }

		  private:
			TryToFire m_Fire;
		};

		class Surrender
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);
		};

		class Ambush
			: public Behavior
		{
		  public:
			Ambush();

			Fuzzy Execute(TacticInterface& i);

			bool ShouldStopImmediately() const;

		  private:
			enum Mode
			{
				RUSH_OUT,
				RUSH_BACK
			};

			Mode m_Mode;

			TryToFire m_Fire;
			bool m_SeenByTarget;
		};

		class DeathFromAbove
			: public Behavior
		{
		  public:
			DeathFromAbove();

			Fuzzy Execute(TacticInterface& i);

			bool ShouldStopImmediately() const;

		  private:
			enum Mode
			{
				WAIT_FOR_FUEL,
				RUSH_IN,
				JUMP,
				FALL
			};

			Mode m_Mode;
			bool m_DoneItOnce;
		};

		class HeliPopup
			: public Behavior
		{
		  public:
			HeliPopup();

			Fuzzy Execute(TacticInterface& i);

			bool ShouldStopImmediately() const;

		  private:
			enum Mode
			{
				POP_UP,
				POP_DOWN
			};

			Mode m_Mode;
			bool m_SeenByTarget;
		};

		class DiveBomb
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);
		};

		class FastCircle
			: public EvasiveBehavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);

		  private:
			TryToFire m_Fire;
			JumpToAvoidCollision m_JumpToAvoidCollision;
		};

		class Stare
			: public Behavior
		{
		  public:
			Fuzzy Execute(TacticInterface& i);
		};

	};
};



#endif // AI_BEHAVIOR_HPP