//=============================================================================
// Xmas Gift entity
// Author: GeckoN
//=============================================================================

namespace PointXmasGift
{

const string ENTITY_NAME = "point_xmas_gift";
const string MODEL_GIFT = "models/xmas_gifts.mdl";

const int GIFT_SKINS = 15;

enum GIFT_SUBMODELS
{
	GIFT_SMALL = 0,
	GIFT_MEDIUM,
	GIFT_LARGE,
};

enum GIFT_SEQ
{
	SEQ_IDLE = 0,
	SEQ_RUMBLE,
};

const array<string> GIFT_PICKUP_SOUNDS =
{
	"gift1.ogg",
	"gift2.ogg",
	"gift3.ogg"
};

const float GIFT_RUMBLE_DELAY = 5.0;

/*const int ACTIVITY_NOT_AVAILABLE = -1;

class CActAnimating : ScriptBaseAnimating
{
private Activity	m_Activity;

	void SetActivity( Activity act )
	{
		int sequence = self.LookupActivity( act );
		if ( sequence != ACTIVITY_NOT_AVAILABLE )
		{
			pev.sequence = sequence;
			m_Activity = act;
			pev.frame = 0;
			self.ResetSequenceInfo( );
		}
	}

	Activity GetActivity() { return m_Activity; }

};*/

class CPointXmasGift : ScriptBaseAnimating
{
	float m_fRumbleTime = 0;
	bool KeyValue( const string& in szKey, const string& in szValue )
	{
		return BaseClass.KeyValue( szKey, szValue );
	}

	// If youre gonna use this in your script, make sure you don't try
	// to access invalid animations. -zode
	void SetAnim( int animIndex )
	{
		pev.sequence = animIndex;
		pev.frame = 0;
		self.ResetSequenceInfo();
	}

	int GetAnim()
	{
		return self.pev.sequence;
	}

	void Precache()
	{
		BaseClass.Precache();

		PrecacheGlobal();
	}

	void Spawn()
	{
		Precache();

		if ( self.pev.movetype != MOVETYPE_NONE_EXPLICIT and self.pev.movetype != MOVETYPE_TOSS and self.pev.movetype != MOVETYPE_FLY and self.pev.movetype != MOVETYPE_NOCLIP )
			self.pev.movetype = MOVETYPE_TOSS;
		self.pev.movetype = ( self.pev.movetype == MOVETYPE_NONE_EXPLICIT ? MOVETYPE_NONE : self.pev.movetype );

		if ( self.pev.solid != SOLID_NOT_EXPLICIT and self.pev.solid != SOLID_TRIGGER and self.pev.solid != SOLID_BBOX )
			self.pev.solid = SOLID_TRIGGER;
		self.pev.solid = ( self.pev.solid == SOLID_NOT_EXPLICIT ? SOLID_NOT : self.pev.solid );

		self.pev.framerate 		= 1.0f;
		self.pev.health			= 1.0f;

		g_EntityFuncs.SetModel( self, MODEL_GIFT );

		g_EntityFuncs.SetSize( self.pev, self.pev.mins, self.pev.maxs);
		g_EntityFuncs.SetOrigin( self, self.pev.origin );

		// Random skin

		self.pev.skin = Math.RandomLong( 0, GIFT_SKINS );

		// Slight yaw variance

		float fAngleVar = 0.0;

		switch ( self.pev.body )
		{
		case GIFT_SMALL:    fAngleVar = 20.0; break;
		case GIFT_MEDIUM:   fAngleVar = 16.0; break;
		case GIFT_LARGE:    fAngleVar = 8.0; break;
		}

		float fAngleVarMul = 1.0 - Math.clamp( 0.0, 1.0, self.pev.scale - 1.0 );
		fAngleVar *= fAngleVarMul;
		self.pev.angles[1] += Math.RandomFloat( -fAngleVar, +fAngleVar );

		SetAnim( SEQ_IDLE ); // set sequence to 0 aka idle

		SetThink( ThinkFunction( this.IdleThink ) );
		self.pev.nextthink = g_Engine.time + 0.1f;
	}

	void Use( CBaseEntity@ pActivator, CBaseEntity@ pCaller, USE_TYPE useType, float value )
	{
		if ( useType == USE_TOGGLE )
		{
			int nSample = Math.RandomLong( 0, GIFT_PICKUP_SOUNDS.length() - 1 );
			g_SoundSystem.EmitSound( pActivator.edict(), CHAN_STATIC, GIFT_PICKUP_SOUNDS[ nSample ], 1.0f, ATTN_NONE );

			self.SUB_UseTargets( pActivator, USE_TOGGLE, 0 );

			self.pev.effects |= EF_NODRAW;
			pev.nextthink = g_Engine.time + 0.1;

			//SetThink( ThinkFunction( ThinkRemove ) );
		}
	}

	void ThinkRemove( void )
	{
		self.SUB_Remove();
	}

	void IdleThink()
	{
		self.StudioFrameAdvance();
		self.pev.nextthink = g_Engine.time + 0.1;

		switch( GetAnim() )
		{
		case SEQ_RUMBLE:
			if ( self.m_fSequenceFinished )
			{
				// Rumble again randomly
				if ( Math.RandomLong( 0, 5 ) < 2 )
				{
					SetAnim( SEQ_RUMBLE );
				}
				else
				{
					m_fRumbleTime = g_Engine.time + GIFT_RUMBLE_DELAY;
					SetAnim( SEQ_IDLE );
				}
			}
			break;

		case SEQ_IDLE:
			// Rumble randomly
			if ( m_fRumbleTime <= g_Engine.time && Math.RandomLong( 0, 14 ) < 1 )
			{
				SetAnim( SEQ_RUMBLE );
			}
			break;

		default:
			break;
		}
	}
}

void PrecacheGlobal()
{
	g_Game.PrecacheModel( MODEL_GIFT );

	for ( uint32 i = 0; i < GIFT_PICKUP_SOUNDS.length(); i++ )
		g_SoundSystem.PrecacheSound( GIFT_PICKUP_SOUNDS[ i ] );
}

void Register()
{
	g_CustomEntityFuncs.RegisterCustomEntity( "PointXmasGift::CPointXmasGift", ENTITY_NAME );
}

} // end of PointXmasGift namespace
