package q2java.baseq2.spawn;

import org.w3c.dom.Element;

import q2java.*;
import q2java.core.*;
import q2java.core.gui.*;
import q2java.baseq2.*;
import q2java.baseq2.event.*;

/**
 * The invulnerability damage power up.
 * @author Brian Haskin
 */
public class item_invulnerability extends GenericPowerUp 
  implements PlayerStateListener, PlayerDamageListener
	{	
	protected Player fOwner;
	protected IconCountdownTimer fHUDTimer;
	protected int fMillis;
	protected boolean fClearEffect;

	protected float fDebounceTime;
	
/**
 * No-arg constructor.
 */
public item_invulnerability() 
	{
	}
public item_invulnerability(Element spawnArgs) throws GameException
	{
	super(spawnArgs);
	}
/**
 * Called by the carrying player when they take damage.
 */
public void damageOccured(PlayerDamageEvent damage)
	{
	float time;
	if ((time = Game.getGameTime()) > fDebounceTime)
		{
		damage.getPlayer().fEntity.sound(NativeEntity.CHAN_ITEM, Engine.getSoundIndex("items/protect4.wav"), 1, NativeEntity.ATTN_NORM, 0);
		fDebounceTime = time + 2;
		}
		
	damage.setArmorSave( damage.getArmorSave() + damage.getAmount() );
	damage.setAmount(0);
	}
/**
 * Get invulnerability icon name.
 * @return java.lang.String
 */
public String getIconName()
	{
	return "p_invulnerability";
	}
/**
 * Get item name.
 * java.lang.String
 */
public String getItemName()
	{
	return "Invulnerability";
	}
/**
 * Get the name of this item's model.
 * @return java.lang.String
 */
public String getModelName() 
	{
	return "models/items/invulner/tris.md2";
	}
/**
 * Invulnerability's don't respawn for 300 seconds, i.e. 5 minutes.
 */
public float getRespawnTime()
	{
	return 300;
	}
/**
 * Undo effects of invulnerability.
 */
protected void reset() 
	{
	if (fOwner != null)
		{
		// reset the player's effects
		fOwner.fEntity.setEffects(fOwner.fEntity.getEffects() & ~NativeEntity.EF_PENT);
	
		// disassociate from the player
		fOwner.removePlayerStateListener(this);		
		fOwner.removePlayerDamageListener(this);
		fOwner = null;
		}
		
	fMillis = 0;
	Game.removeServerFrameListener(this);

	if (fHUDTimer != null)
		{
		fHUDTimer.setVisible(false);
		fHUDTimer.setRunning(false);
		}	
	}
/**
 * Play any sounds that we need to and clean up when time's up.
 */
public void runFrame(int Phase)
	{
	if (fOwner == null)	// Someone above us must want it. - Is this really needed?
		{
		super.runFrame(Phase);
		return;
		}
	
	if (fMillis-- > 30)
		{
		fOwner.addBlend(1f, 1f, 0f, 0.08f);
		}
	else if ((fMillis & 4) == 4)
		{
		fOwner.addBlend(1f, 1f, 0f, 0.08f);
		fOwner.fEntity.setEffects(fOwner.fEntity.getEffects() | NativeEntity.EF_PENT);
		fClearEffect = true;
		}
	else if (fClearEffect)
		{
		fOwner.fEntity.setEffects(fOwner.fEntity.getEffects() & ~NativeEntity.EF_PENT);
		fClearEffect = false;
		}
	
	if (fMillis == 30)
		{
		fOwner.fEntity.sound( NativeEntity.CHAN_ITEM, Engine.getSoundIndex("items/protect2.wav"), 1, NativeEntity.ATTN_NORM, 0);
		}
	
	if (fMillis == 0)
		reset();
	}
/**
 * Called by the carrying player when they die. This gives us the chance to reset 
 * their effects if we were in use when they died.
 */
public void stateChanged(PlayerStateEvent pse)
	{
	switch (pse.getStateChanged())	
		{
		case PlayerStateEvent.STATE_DEAD:
		case PlayerStateEvent.STATE_INVALID:
		case PlayerStateEvent.STATE_SUSPENDEDSTART:
			reset();
			break;
		}
	}
/**
 * When used don't allow the Player to be damaged for 30 seconds.
 */
public void use(Player p)
	{
	fOwner = p;
	
	Game.addServerFrameListener(this, 0, 0); // Call us every frame
	fOwner.addPlayerStateListener(this);
	fOwner.addPlayerDamageListener(this);
	
	fMillis += 300;
	
	if (fHUDTimer == null)
		{
		fHUDTimer = new IconCountdownTimer(fOwner.fEntity, NativeEntity.STAT_TIMER_ICON, Engine.getImageIndex("p_invulnerability"), NativeEntity.STAT_TIMER, (fMillis/10)-1);
		fHUDTimer.setVisible(true);
		fHUDTimer.setRunning(true);
		}
	else
		{
		fHUDTimer.setValue((fMillis/10)-1);
		fHUDTimer.setVisible(true);
		fHUDTimer.setRunning(true);
		}
	
	fOwner.fEntity.sound( NativeEntity.CHAN_ITEM, Engine.getSoundIndex("items/protect.wav"), 1, NativeEntity.ATTN_NORM, 0);
	fOwner.fEntity.setEffects(fOwner.fEntity.getEffects() | NativeEntity.EF_PENT);
	}
}