namespace poison_alien_grunt
{
    //const Vector HEV_SCREEN_COLOR( 0, 255, 50 );
    const array<Vector> PLAYER_PUNCH_CAMERA = { Vector( 0, -1.5, 0 ), Vector( 0, 1.5, 0 ) };
    const float POISON_DURATION = 5.0f;
    const float POISON_DAMAGE_PER_SECOND2 = 0;	// increase this for more damage
    const int POISON_MAX_SECONDS = 5;

    const bool g_Registry = Register();

    bool Register()
    {
        g_Hooks.RegisterHook( Hooks::Player::PlayerTakeDamage, @TakeDamage );
		g_Hooks.RegisterHook( Hooks::Monster::MonsterTakeDamage, @TakeDamage );
		g_Hooks.RegisterHook( Hooks::Game::EntityCreated, @OnEntityCreated );
        return true;
    }

	void Precache()
	{
		g_Game.PrecacheModel( "sprites/insecure/muz9.spr" );
	}	

    array<float> g_LastPlayerHevNotice(32);

    HookReturnCode TakeDamage( DamageInfo@ info )
    {
	
		if (g_Engine.mapname == "insecure_06d") //// Poisonous Alien Grunts only appear here.
		{
			if( ( info.bitsDamageType & DMG_POISON ) != 0
			|| info.pVictim is null
			|| info.pInflictor is null
			|| info.pInflictor.pev.owner is null
			|| info.pInflictor.GetClassname() != "hornet" ) {
				return HOOK_CONTINUE;
			}
	
			if( info.pVictim.IsPlayer() )
			{
				auto player = cast<CBasePlayer@>( info.pVictim );

				player.pev.punchangle.y = Math.RandomFloat( PLAYER_PUNCH_CAMERA[0][0], PLAYER_PUNCH_CAMERA[1][0] );
				player.pev.punchangle.x = Math.RandomFloat( PLAYER_PUNCH_CAMERA[0][1], PLAYER_PUNCH_CAMERA[1][1] );
				player.pev.punchangle.z = Math.RandomFloat( PLAYER_PUNCH_CAMERA[0][2], PLAYER_PUNCH_CAMERA[1][2] );

				//g_PlayerFuncs.ScreenFade( player, HEV_SCREEN_COLOR, 0.5f, POISON_DURATION, 255, FFADE_MODULATE );
			}

			info.flDamage = (g_EngineFuncs.CVarGetFloat( "sk_hornet_pdmg" )*1);

			auto ckv = info.pVictim.GetCustomKeyvalues();

			if( ckv.GetKeyvalue( "$i_poison" ).GetInteger() >= 0 )
			{
				ckv.SetKeyvalue( "$i_poison", POISON_MAX_SECONDS );
				g_Scheduler.SetTimeout( "ApplyPoison2", 1.0f, EHandle(info.pVictim), EHandle(info.pAttacker) );
			}

			
			// muzzle sprite when hornet hits target
			if( info.pInflictor !is null && info.pInflictor.GetClassname() == "hornet" )
			{
				Vector start = info.pInflictor.pev.origin;
				Vector dir = info.pInflictor.pev.velocity.Normalize();
	
				TraceResult tr;
				g_Utility.TraceLine( start, start + dir * 16, dont_ignore_monsters, info.pInflictor.edict(), tr );
	
				Vector vecPos = tr.vecEndPos;
	
				NetworkMessage m( MSG_PVS, NetworkMessages::SVC_TEMPENTITY, vecPos );
				m.WriteByte( TE_SPRITE );
				m.WriteCoord( vecPos.x );
				m.WriteCoord( vecPos.y );
				m.WriteCoord( vecPos.z );
				m.WriteShort( g_EngineFuncs.ModelIndex( "sprites/insecure/muz9.spr" ) );
				m.WriteByte( 5 );
				m.WriteByte( 200 );
				m.End();
			}
		
			// buzz when you plug someone
			switch (Math.RandomLong(0,2))
			{
				case 0:	g_SoundSystem.EmitSoundDyn( info.pInflictor.edict(), CHAN_VOICE, "insecure/phornet/ph_hornethit1.wav", 1, ATTN_NORM);	break;
				case 1:	g_SoundSystem.EmitSoundDyn( info.pInflictor.edict(), CHAN_VOICE, "insecure/phornet/ph_hornethit2.wav", 1, ATTN_NORM);	break;
				case 2:	g_SoundSystem.EmitSoundDyn( info.pInflictor.edict(), CHAN_VOICE, "insecure/phornet/ph_hornethit3.wav", 1, ATTN_NORM);	break;
			}
		}
        return HOOK_CONTINUE;
	}

    void ApplyPoison2( EHandle hVictim, EHandle hAttacker )
    {
        if( !hVictim.IsValid() )
            return;

        auto victim = hVictim.GetEntity();

        auto ckv = victim.GetCustomKeyvalues();

        int current = ckv.GetKeyvalue( "$i_poison" ).GetInteger();

        if( current == 0 )
            return;

		if ( g_Engine.mapname == "insecure_06d" ) //// Poisonous Alien Grunts only appear here.
		{
			entvars_t@ attacker = hAttacker.IsValid() ? hAttacker.GetEntity().pev : null;
			victim.TakeDamage( attacker, attacker, POISON_DAMAGE_PER_SECOND2, ( DMG_POISON ) );
			ckv.SetKeyvalue( "$i_poison", current - 1 );
			g_Game.AlertMessage( at_console, "Poison call %1\n", current );
			g_Scheduler.SetTimeout( "ApplyPoison2", 1.0f, hVictim, hAttacker );
		}
    }
}

/*
HookReturnCode OnEntityCreated( CBaseEntity@ pEnt )
{
    if( pEnt is null )
        return HOOK_CONTINUE;

    if( g_Engine.mapname != "insecure_06d" ) // Poisonous Alien Grunts only appear in this map.
        return HOOK_CONTINUE;

//	if( pEnt.GetClassname() == "hornet" )
//	{
//		g_Scheduler.SetTimeout( "ModifyHornet", 0.0f, EHandle(pEnt) );
//	}

    return HOOK_CONTINUE;
}