package cz.cuni.amis.pogamut.ut2004.bot.commands;

import cz.cuni.amis.pogamut.base3d.worldview.objects.ILocated;
import cz.cuni.amis.pogamut.ut2004.bot.AbstractUT2004Bot;
import cz.cuni.amis.pogamut.ut2004.communication.messages.UnrealId;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.*;

import java.util.logging.Logger;

/**
 * Class providing Pogamut2 UT2004 advanced shooting commands for the bot - shooting
 * in secondary mode, grenade launcher shooting, etc.
 *
 * @author Michal 'Knight' Bida
 */
public class AdvancedShooting extends BotCommands
{

        /** 
         * Bot will start shooting his current weapon with selected mode. 
         * 
         * (issues GB SHOOT command) 
         * 
         * @param secondaryMode If true secondary firing mode will be issued.
         * 
         */    
        public void shootWithMode(boolean secondaryMode)
        {
            Shoot shoot = new Shoot();
            shoot.setAlt(secondaryMode);
            agent.getAct().act(shoot);
        }

        /** 
         * Bot will start shooting his current weapon with primary firing mode at
         * the location specified. The bot will shoot on this location even when he will
         * turn a little bit from the direction to the location. If he turn out more
         * then approx 15 - 30 degrees he won't be able to hit the location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param location Location we will be shooting at.
         * 
         * @see shootPrimary(UnrealId)
         */         
        public void shootPrimary(ILocated location)
        {
            Shoot shoot = new Shoot();
            shoot.setLocation(location.getLocation());
            agent.getAct().act(shoot);            
        }
       
        /** 
         * Bot will start shooting his current weapon with primary firing mode at
         * the target specified. The target should exist in the environment. The
         * bot will track the target in the environment as long as other commands 
         * won't change his focus (strafe(), turnTo()..). If they will the bot will still
         * shoot on target location until he will turn from target more then approx
         * 15 - 30 degrees. Then he won't be able to hit the target location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param target Object in the environment we will shoot at.
         * 
         * @see shootPrimary(ILocated)
         */         
        public void shootPrimary(UnrealId target)
        {
            Shoot shoot = new Shoot();
            shoot.setTarget(target);
            agent.getAct().act(shoot);             
        }        
       
        /** 
         * Bot will start shooting his current weapon with secondary firing mode at
         * the location specified. The bot will shoot on this location even when he will
         * turn a little bit from the direction to the location. If he turn out more
         * then approx 15 - 30 degrees he won't be able to hit the location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param location Location we will be shooting at.
         * 
         * @see shootSecondary(UnrealId)
         */             
        public void shootSecondary(ILocated location)
        {
            Shoot shoot = new Shoot();
            shoot.setLocation(location.getLocation());
            shoot.setAlt(true);
            agent.getAct().act(shoot);                        
        }  
        
        /** 
         * Bot will start shooting his current weapon with secondary firing mode at
         * the target specified. The target should exist in the environment. The
         * bot will track the target in the environment as long as other commands 
         * won't change his focus (strafe(), turnTo()..). If they will the bot will still
         * shoot on target location until he will turn from target more then approx
         * 15 - 30 degrees. Then he won't be able to hit the target location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param target Object in the environment we will shoot at.
         * 
         * @see shootSecondary(ILocated)
         */          
        public void shootSecondary(UnrealId target)
        {
            Shoot shoot = new Shoot();
            shoot.setTarget(target);
            shoot.setAlt(true);            
            agent.getAct().act(shoot);        
        }
        
        /** 
         * This method can be used for UT2004 charging weapons. Some weapons in UT2004
         * feature charging firing modes. These modes works as follows. To shoot with 
         * a charging firing mode the bot has to start shooting first - this will trigger
         * the weapon to start charging (it won't fire yet). 
         * To fire the weapon the bot needs to send STOPSHOOT command to stop charging
         * the weapon and to release the projectile. This method does this automatically
         * for primary firing mode of the weapon. The time of charging can be specified
         * too (second parameter in seconds). 
         * 
         * This method can be also used for non-charing (primary) firing mode of the weapon - 
         * then it will work as burst fire - the bot will continue firing for the amout 
         * of seconds specified.
         * 
         * So if the current weapon primary firing mode is charging, the bot will release
         * the projectiles once. With normal primary firing mode the bot will fire a burst.
         * 
         * Note: We will shoot at location specified. The bot will continue to aim
         * on the location in the environment (for the time of charging or bursting)
         * as long as other commands won't change his focus (strafe(), turnTo()..). 
         * If they will the bot will still shoot on location until he will turn 
         * from it more then approx 15 - 30 degrees. Then he won't be able to hit
         * the location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param location Location we will be shooting at.
         * @param chargeTime In seconds - how long we will charge the weapon (or how long will be the burst fire). 
         * 
         * @see shootPrimaryCharged(UnrealId, double)
         */        
        public void shootPrimaryCharged(ILocated location, double chargeTime)
        {
            Shoot shoot = new Shoot();
            shoot.setLocation(location.getLocation());
            agent.getAct().act(shoot);    
            //TODO: Implement somehow the charging delay
            agent.getAct().act(new StopShooting());
        }
  
        /** 
         * This method can be used for UT2004 charging weapons. Some weapons in UT2004
         * feature charging firing modes. These modes works as follows. To shoot with 
         * a charging firing mode the bot has to start shooting first - this will trigger
         * the weapon to start charging (it won't fire yet). 
         * To fire the weapon the bot needs to send STOPSHOOT command to stop charging
         * the weapon and to release the projectile. This method does this automatically
         * for primary firing mode of the weapon. The time of charging can be specified
         * too (second parameter in seconds). 
         * 
         * This method can be also used for non-charing (primary) firing mode of the weapon - 
         * then it will work as burst fire - the bot will continue firing for the amout 
         * of seconds specified.
         * 
         * So if the current weapon primary firing mode is charging, the bot will release
         * the projectiles once. With normal primary firing mode the bot will fire a burst.
         * 
         * Note: The target for shooting should exist in the environment. The
         * bot will track the target in the environment (for the time of charging or bursting)
         * as long as other commands won't change his focus (strafe(), turnTo()..). 
         * If they will the bot will still shoot on target location until he will turn 
         * from target more then approx 15 - 30 degrees. Then he won't be able to hit
         * the target location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param target Object in the environment we will shoot at (basic tracking provided).
         * @param chargeTime In seconds - how long we will charge the weapon (or how long will be the burst fire). 
         * 
         * @see shootPrimaryCharged(ILocated, double)
         * 
         * @todo Implement somehow the charging delay.
         */           
        public void shootPrimaryCharged(UnrealId target, double chargeTime)
        {
            Shoot shoot = new Shoot();
            shoot.setTarget(target);
            agent.getAct().act(shoot);   
            //TODO: Implement somehow the charging delay
            agent.getAct().act(new StopShooting());
        }        
        
        /** 
         * This method can be used for UT2004 charging weapons. Some weapons in UT2004
         * feature charging firing modes. These modes works as follows. To shoot with 
         * a charging firing mode the bot has to start shooting first - this will trigger
         * the weapon to start charging (it won't fire yet). 
         * To fire the weapon the bot needs to send STOPSHOOT command to stop charging
         * the weapon and to release the projectile. This method does this automatically
         * for secondary firing mode of the weapon. The time of charging can be specified
         * too (second parameter in seconds). 
         * 
         * This method can be also used for non-charing (secondary) firing mode of the weapon - 
         * then it will work as burst fire - the bot will continue firing for the amout 
         * of seconds specified.
         * 
         * So if the current weapon secondary firing mode is charging, the bot will release
         * the projectiles once. With normal secondary firing mode the bot will fire a burst.
         * 
         * Note: We will shoot at location specified. The bot will continue to aim
         * on the location in the environment (for the time of charging or bursting)
         * as long as other commands won't change his focus (strafe(), turnTo()..). 
         * If they will the bot will still shoot on location until he will turn 
         * from it more then approx 15 - 30 degrees. Then he won't be able to hit
         * the location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param location Location we will be shooting at.
         * @param chargeTime In seconds - how long we will charge the weapon (or how long will be the burst fire). 
         * 
         * @see shootSecondaryCharged(UnrealId, double)
         * 
         * @todo Implement somehow the charging delay.
         */         
        public void shootSecondaryCharged(ILocated location, double chargeTime)
        {
            Shoot shoot = new Shoot();
            shoot.setLocation(location.getLocation());
            shoot.setAlt(true);
            agent.getAct().act(shoot); 
            //TODO: Implement somehow the charging delay
            agent.getAct().act(new StopShooting());
        }
        
        /** 
         * This method can be used for UT2004 charging weapons. Some weapons in UT2004
         * feature charging firing modes. These modes works as follows. To shoot with 
         * a charging firing mode the bot has to start shooting first - this will trigger
         * the weapon to start charging (it won't fire yet). 
         * To fire the weapon the bot needs to send STOPSHOOT command to stop charging
         * the weapon and to release the projectile. This method does this automatically
         * for secondary firing mode of the weapon. The time of charging can be specified
         * too (second parameter in seconds). 
         * 
         * This method can be also used for non-charing (secondary) firing mode of the weapon - 
         * then it will work as burst fire - the bot will continue firing for the amout 
         * of seconds specified.
         * 
         * So if the current weapon secondary firing mode is charging, the bot will release
         * the projectiles once. With normal secondary firing mode the bot will fire a burst.
         * 
         * Note: The target for shooting should exist in the environment. The
         * bot will track the target in the environment (for the time of charging or bursting)
         * as long as other commands won't change his focus (strafe(), turnTo()..). 
         * If they will the bot will still shoot on target location until he will turn 
         * from target more then approx 15 - 30 degrees. Then he won't be able to hit
         * the target location anymore.
         * 
         * (issues GB SHOOT command) 
         * 
         * @param target Object in the environment we will shoot at (basic tracking provided).
         * @param chargeTime In seconds - how long we will charge the weapon (or how long will be the burst fire). 
         * 
         * @see shootSecondaryCharged(ILocated, double)
         * 
         * @todo Implement somehow the charging delay.
         */           
        public void shootSecondaryCharged(UnrealId target, double chargeTime)
        {
            Shoot shoot = new Shoot();
            shoot.setTarget(target);
            shoot.setAlt(true);            
            agent.getAct().act(shoot); 
            //TODO: Implement somehow the charging delay
            agent.getAct().act(new StopShooting());
        }        
        
	/**
	 * Constructor. Setups the command module based on given agent and logger.
	 * @param agent AbstractUT2004Bot we will send commands for
	 * @param log Logger to be used for logging runtime/debug info.
         * 
         * @todo Implement somehow the charging delay.
	 */        
        public AdvancedShooting(AbstractUT2004Bot agent, Logger log)
	{
		super(agent, log);                
	}
        
}