/******************************************************************
  
  Module:  aigoal_noncombat.h
  
  Author: Borut Pfeifer
  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/
#ifndef AIGOAL_NONCOMBAT_H
#define AIGOAL_NONCOMBAT_H

//-------------------------------------------------------- Includes
#include "aigoal.h"

//---------------------------------------------- Class Declarations
class SyFrustum;


class cGoal_Goto : public cAiGoal
{
public:
  cGoal_Goto(const SyVect3 &destination):mDestination(destination){};
  virtual void Update(float time);
  virtual eGoalType GetType(){return GOAL_GOTO;};
protected:
  SyVect3     mDestination;
};


class cGoal_Patrol : public cAiGoal
{
public:
  cGoal_Patrol();
  ~cGoal_Patrol();

  virtual void Update(float time);
  virtual eGoalType GetType(){return GOAL_PATROL;};

  void AddWaypoint(const SyVect3& markerLoc, float speed, float pauseTime);
  void ClearWaypoints();
  void SetLooping(bool bLoop);

protected:
  struct Waypoint
  {
    SyVect3 mLoc;
    float mPauseTime;
    float mSpeed;
  };

  SyVector<Waypoint>   mWaypoints;
  int                  mCurWaypoint;
  float                mCurWait;
  bool                 mbLoop;
};

class cGoal_Fade : public cAiGoal
{
public:
  cGoal_Fade();

  virtual eGoalType GetType(){return GOAL_FADEAWAY;};
  virtual void Update(float time);

private:
  float mTime;
};

class cGoal_Stand : public cAiGoal
{
public:
  cGoal_Stand(float waitTime = -1.0f);
  virtual eGoalType GetType(){return GOAL_STAND;};
  virtual void Update(float time);

protected:
  float mWaitTime;
};

class cGoal_Flee : public cAiGoal
{
public:
  cGoal_Flee(tGameObjectID target, float time, float goalDistance);
  cGoal_Flee(const SyVect3& pos, float time, float goalDistance);

  virtual eGoalType GetType(){return GOAL_FLEE;};
  virtual void Update(float time);

  cGameObject* GetTarget();

protected:
  tGameObjectID mTargetID;
  float         mTimer;
  float         mGoalDist;

  bool      mbUseAvoidPosition;
  SyVect3   mAvoidPosition;
};

class cGoal_Wander : public cAiGoal
{
public:
  cGoal_Wander(float time);

  virtual void Enter();
  virtual void Update(float time);
  virtual eGoalType GetType(){return GOAL_WANDER;};

protected:
  cAIWanderSteering mWander;
  float mTimer;
};


class cGoal_WanderNear : public cGoal_Wander
{
public:
  cGoal_WanderNear(const SyVect3& targetLoc, float dist);

  virtual void Enter();
  virtual void Update(float time);
  virtual eGoalType GetType(){return GOAL_WANDER;};

protected:
  SyVect3 mTargetLoc;
  float mTargetDist;
};

class cGoal_OnFire : public cAiGoal
{
public:
  cGoal_OnFire();

  virtual void Enter();
  virtual void Update(float time);
  virtual eGoalType GetType(){return GOAL_WANDER;};

protected:
  cAIWanderSteering mWander;
};

class cLocationSnapshotTaker
{
public:
  cLocationSnapshotTaker();

  struct TargetSnapshot
  {
    bool Approx(const TargetSnapshot& ss) const;

    SyVect3 mLocation;
    SyTime mTimestamp;
  };

  void Update(cGameObject* pTarget, float time);
  void TakeSnapshot(cGameObject* pTarget);
  bool FindTeleportSnapshot(cGameObject* pTarget, const SyFrustum& frustum, TargetSnapshot& ss);
  bool FindNearestSnapshot(const SyVect3& loc, TargetSnapshot& ss);
  bool FindNextSnapshot(const SyTime& timestamp, TargetSnapshot& ss);

private:
  MemoryQueue<TargetSnapshot> mTargetData;
  float mTimeSinceLastSnapshot;
};

class cGoal_Follow : public cAiGoal
{
public:
  cGoal_Follow(tGameObjectID targetID);

  virtual eGoalType GetType(){return GOAL_FOLLOW;};

  virtual void Enter();
  virtual void Update(float time);
  virtual void Exit();

protected:
  void Teleport();
  void GotoSnapshot();

  tGameObjectID mTargetID;
  cLocationSnapshotTaker mSnapshots;
  bool mbFollowingSnapshots;
  SyTime mLastFollowedSnapshotTime;
};

class cGoal_Defend : public cGoal_Follow
{
public:
  cGoal_Defend(tGameObjectID targetID);

  virtual void Enter();
  virtual void Update(float time);
  virtual void Exit();

protected:
  void MoveToDefendPosition(float speed);
};

class cGoal_Hunt : public cAiGoal
{
public:
  cGoal_Hunt(tGameObjectID targetID, const SyVect3& startLoc);

  virtual eGoalType GetType(){return GOAL_HUNT;};

  virtual void Enter();
  virtual void Update(float time);
  virtual void Exit();

protected:
  void GotoSnapshot();
  void SearchForInvisibleTarget(cGameObject* pTarget, float time, float speed);

  tGameObjectID           mTargetID;
  cLocationSnapshotTaker  mSnapshots;
  bool                    mbFollowingSnapshots;
  SyTime                  mLastFollowedSnapshotTime;
  SyVect3                 mStartLoc;
  bool                    mbVisitedStartLoc;
  float                   mSearchTimer;
  cAIWanderSteering       mSearchWander;
  float                   mRandTime;
};

#endif
