//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Engineer's Dispenser
//
// $NoKeywords: $
//=============================================================================//

#ifndef TF_OBJ_DISPENSER_H
#define TF_OBJ_DISPENSER_H
#ifdef _WIN32
#pragma once
#endif

#include "tf_obj.h"
#include "triggers.h"

class CTFPlayer;

#define DISPENSER_MAX_HEALTH	150

#define DISPENSER_MINI_MAX_HEALTH	100
#define DISPENSER_MINI_MAX_LEVEL	1
#define DISPENSER_MINI_HEAL_RATE	10.0 
#define DISPENSER_MINI_AMMO_RATE	0.2 
#define DISPENSER_MINI_AMMO_THINK	0.5

#define SF_DISPENSER_IGNORE_LOS					(SF_BASEOBJ_INVULN<<1)
#define SF_DISPENSER_DONT_HEAL_DISGUISED_SPIES	(SF_BASEOBJ_INVULN<<2)	

// ------------------------------------------------------------------------ //
// Repair Trigger
// ------------------------------------------------------------------------ //
class CDispenserTouchTrigger : public CBaseTrigger
{
	DECLARE_CLASS( CDispenserTouchTrigger, CBaseTrigger );

public:
	CDispenserTouchTrigger() {}

	void Spawn( void )
	{
		BaseClass::Spawn();
		AddSpawnFlags( SF_TRIGGER_ALLOW_CLIENTS );
		InitTrigger();
	}

	virtual void StartTouch( CBaseEntity *pEntity )
	{
		if ( PassesTriggerFilters( pEntity ) )
		{
			CBaseEntity *pParent = GetOwnerEntity();

			if ( pParent )
			{
				pParent->StartTouch( pEntity );
			}
		}
	}

	virtual void EndTouch( CBaseEntity *pEntity )
	{
		if ( PassesTriggerFilters( pEntity ) )
		{
			CBaseEntity *pParent = GetOwnerEntity();

			if ( pParent )
			{
				pParent->EndTouch( pEntity );
			}
		}
	}
};

// Ground placed version
#define DISPENSER_MODEL_PLACEMENT		"models/buildables/dispenser_blueprint.mdl"
#define DISPENSER_MODEL_BUILDING		"models/buildables/dispenser.mdl"
#define DISPENSER_MODEL					"models/buildables/dispenser_light.mdl"
#define DISPENSER_MODEL_BUILDING_LVL2	"models/buildables/dispenser_lvl2.mdl"
#define DISPENSER_MODEL_LVL2			"models/buildables/dispenser_lvl2_light.mdl"
#define DISPENSER_MODEL_BUILDING_LVL3	"models/buildables/dispenser_lvl3.mdl"
#define DISPENSER_MODEL_LVL3			"models/buildables/dispenser_lvl3_light.mdl"

#ifdef STAGING_ONLY
// Mini models
#define MINI_DISPENSER_MODEL_PLACEMENT		"models/workshop/buildables/mini_dispenser/mini_dispenser.mdl"
#define MINI_DISPENSER_MODEL_BUILDING		"models/workshop/buildables/mini_dispenser/mini_dispenser.mdl"
#define MINI_DISPENSER_MODEL				"models/workshop/buildables/mini_dispenser/mini_dispenser.mdl"
#endif // STAGING_ONLY

// ------------------------------------------------------------------------ //
// Resupply object that's built by the player
// ------------------------------------------------------------------------ //
class CObjectDispenser : public CBaseObject
{
	DECLARE_CLASS( CObjectDispenser, CBaseObject );

public:
	DECLARE_SERVERCLASS();

	CObjectDispenser();
	~CObjectDispenser();

	static CObjectDispenser* Create(const Vector &vOrigin, const QAngle &vAngles);

	virtual void	Spawn() OVERRIDE;
	virtual void	FirstSpawn( void ) OVERRIDE;
	virtual void	GetControlPanelInfo( int nPanelIndex, const char *&pPanelName ) OVERRIDE;
	virtual void	Precache() OVERRIDE;

	virtual void	DetonateObject( void ) OVERRIDE;
	virtual void	DestroyObject( void ) OVERRIDE;		// Silent cleanup

	virtual void	OnGoActive( void );	
	virtual void	StartPlacement( CTFPlayer *pPlayer ) OVERRIDE;
	virtual bool	StartBuilding( CBaseEntity *pBuilder ) OVERRIDE;
	virtual void	SetStartBuildingModel( void ) OVERRIDE;
	virtual int		DrawDebugTextOverlays(void) OVERRIDE;
	virtual void	SetModel( const char *pModel ) OVERRIDE;
	virtual void	InitializeMapPlacedObject( void ) OVERRIDE;
	virtual bool	ShouldBeMiniBuilding( CTFPlayer* pPlayer ) OVERRIDE;

	virtual bool	IsUpgrading( void ) const OVERRIDE { return ( m_iState == DISPENSER_STATE_UPGRADING ); }
	virtual void	StartUpgrading( void ) OVERRIDE;
	virtual void	FinishUpgrading( void ) OVERRIDE;

	virtual int		DispenseMetal( CTFPlayer *pPlayer );
	virtual int		GetAvailableMetal( void ) const;

	virtual void RefillThink( void );
	virtual void DispenseThink( void );

	virtual void StartTouch( CBaseEntity *pOther ) OVERRIDE;
	virtual void Touch( CBaseEntity *pOther ) OVERRIDE;
	virtual void EndTouch( CBaseEntity *pOther ) OVERRIDE;

	virtual const char* GetBuildingModel( int iLevel );
	virtual const char* GetFinishedModel( int iLevel );
	virtual const char* GetPlacementModel();

	virtual int	ObjectCaps( void ) OVERRIDE { return (BaseClass::ObjectCaps() | FCAP_IMPULSE_USE); }

	virtual bool DispenseAmmo( CTFPlayer *pPlayer );

	virtual void DropSpellPickup() { /* DO NOTHING */ }
	virtual void DropDuckPickup() { /* DO NOTHING */ }
	virtual void DispenseSouls() { /* Do nothing */}

	virtual float GetHealRate() const;
	virtual void StartHealing( CBaseEntity *pOther );
	void StopHealing( CBaseEntity *pOther );

	void AddHealingTarget( CBaseEntity *pOther );
	bool RemoveHealingTarget( CBaseEntity *pOther );
	bool IsHealingTarget( CBaseEntity *pTarget );

	bool CouldHealTarget( CBaseEntity *pTarget );
	virtual float GetDispenserRadius( void );


	Vector GetHealOrigin( void );

	CUtlVector< EHANDLE >	m_hHealingTargets;

	virtual void	MakeMiniBuilding( CTFPlayer* pPlayer ) OVERRIDE;
	virtual void	MakeCarriedObject( CTFPlayer *pCarrier );

	virtual int		GetBaseHealth( void ) { return DISPENSER_MAX_HEALTH; }

	virtual int		GetMaxUpgradeLevel( void ) OVERRIDE;

	virtual int		GetMiniBuildingStartingHealth( void ) OVERRIDE { return DISPENSER_MINI_MAX_HEALTH; }

	CBaseEntity		*GetTouchTrigger() const { return m_hTouchTrigger; }
	void			DisableAmmoPickupSound() { m_bPlayAmmoPickupSound = false; }
	void			DisableGenerateMetalSound() { m_bUseGenerateMetalSound = false; }

private:
	virtual void PlayActiveSound();
	void ResetHealingTargets( void );

protected:

	// The regular and mini dispenser can be repaired
	virtual bool CanBeRepaired() const OVERRIDE { return true; }

	CNetworkVar( int, m_iState );
	CNetworkVar( int, m_iAmmoMetal );
	CNetworkVar( int, m_iMiniBombCounter );

	bool m_bUseGenerateMetalSound;

	// Entities currently being touched by this trigger
	CUtlVector< EHANDLE >	m_hTouchingEntities;

	float m_flNextAmmoDispense;

	bool m_bThrown;

	string_t m_iszCustomTouchTrigger;
	EHANDLE m_hTouchTrigger;

	DECLARE_DATADESC();

private:

	CountdownTimer m_spellTimer;
	CountdownTimer m_duckTimer;
	CountdownTimer m_soulTimer;

	float m_flPrevRadius;
	bool m_bPlayAmmoPickupSound;
};

inline int CObjectDispenser::GetAvailableMetal( void ) const
{
	return m_iAmmoMetal;
}


//------------------------------------------------------------------------------
class CObjectCartDispenser : public CObjectDispenser
{
	DECLARE_CLASS( CObjectCartDispenser, CObjectDispenser );

public:
	DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	CObjectCartDispenser();

	virtual void Spawn( void );
	virtual void OnGoActive( void );
	virtual void GetControlPanelInfo( int nPanelIndex, const char *&pPanelName );

	virtual int	DispenseMetal( CTFPlayer *pPlayer );
	virtual void DropSpellPickup();
	virtual void DropDuckPickup();
	virtual void DispenseSouls() OVERRIDE;

	virtual bool	CanBeUpgraded( CTFPlayer *pPlayer ){ return false; }
	virtual void	SetModel( const char *pModel );

	void InputFireHalloweenBonus( inputdata_t &inputdata );
	void InputSetDispenserLevel( inputdata_t &inputdata );
	void InputEnable( inputdata_t &inputdata );
	void InputDisable( inputdata_t &inputdata );
};

#endif // TF_OBJ_DISPENSER_H