//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//
//=============================================================================//
// fish.h
// Simple fish behavior
// Author: Michael S. Booth, April 2005

#ifndef _FISH_H_
#define _FISH_H_

#include "baseanimating.h"
#include "GameEventListener.h"

class CFishPool;

//----------------------------------------------------------------------------------------------
/**
 * Simple ambient fish
 */
class CFish : public CBaseAnimating
{
public:
	DECLARE_CLASS( CFish, CBaseAnimating );
	DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	CFish( void );
	virtual ~CFish();

	void Initialize( CFishPool *pool, unsigned int id );
	
	virtual void Spawn( void );

	virtual void Event_Killed( const CTakeDamageInfo &info );
	virtual void Touch( CBaseEntity *other );			///< in contact with "other"

	void Update( float deltaT );						///< invoked each server tick

	void FlockTo( CFish *other, float amount );			///< influence my motion to flock with other nearby fish
	float Avoid( void );
	void Panic( void );									///< panic for awhile

	void ResetVisible( void );							///< zero the visible vector
	void AddVisible( CFish *fish );						///< add this fish to our visible vector

private:
	friend void SendProxy_FishOriginX( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );
	friend void SendProxy_FishOriginY( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID );

	CHandle<CFishPool> m_pool;							///< the pool we are in
	unsigned int m_id;									///< our unique ID

	CNetworkVar( float, m_x );							///< have to send position coordinates separately since Z is unused
	CNetworkVar( float, m_y );							///< have to send position coordinates separately since Z is unused
	CNetworkVar( float, m_z );							///< only sent once since fish always swim at the same depth

	CNetworkVar( float, m_angle );						///< only yaw changes
	float m_angleChange;
	Vector m_forward;
	Vector m_perp;

	CNetworkVar( Vector, m_poolOrigin );				///< used to efficiently network our relative position
	CNetworkVar( float, m_waterLevel );

	float m_speed;
	float m_desiredSpeed;

	float m_calmSpeed;									///< speed the fish moves when calm
	float m_panicSpeed;									///< speed the fish moves when panicked

	float m_avoidRange;									///< range to avoid obstacles

	CountdownTimer m_turnTimer;							///< every so often our turn preference changes
	bool m_turnClockwise;								///< if true this fish prefers to turn clockwise, else CCW
	
	CountdownTimer m_goTimer;							///< start the fish moving when timer elapses
	CountdownTimer m_moveTimer;							///< dont decay speed while we are moving
	CountdownTimer m_panicTimer;						///< if active, fish is panicked
	CountdownTimer m_disperseTimer;						///< initial non-flocking time

	CUtlVector< CFish * > m_visible;					///< vector of fish that we can see
};


//----------------------------------------------------------------------------------------------
/**
 * This class defines a volume of water where a number of CFish swim
 */
class CFishPool : public CBaseEntity, public CGameEventListener
{
public:
	DECLARE_CLASS( CFishPool, CBaseEntity );
	DECLARE_DATADESC();

	CFishPool( void );

	virtual void Spawn();

	virtual bool KeyValue( const char *szKeyName, const char *szValue );

	virtual void FireGameEvent( IGameEvent *event );

	void Update( void );					///< invoked each server tick

	float GetWaterLevel( void ) const;		///< return Z coordinate of water in world coords
	float GetMaxRange( void ) const;		///< return how far a fish is allowed to wander

private:
	int m_fishCount;						///< number of fish in the pool
	float m_maxRange;						///< how far a fish is allowed to wander
	float m_swimDepth;						///< the depth the fish swim below the water surface

	float m_waterLevel;						///< Z of water surface

	bool m_isDormant;

	CUtlVector< CHandle<CFish> > m_fishes;	///< vector of all fish in this pool

	CountdownTimer m_visTimer;				///< for throttling line of sight checks between all fish
};


inline float CFishPool::GetMaxRange( void ) const
{
	return m_maxRange;
}


inline float CFishPool::GetWaterLevel( void ) const
{
	return m_waterLevel;
}


#endif // _FISH_H_