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


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

import java.util.logging.Logger;
import javax.vecmath.Vector3d;

/**
 * Class providing Pogamut2 UT2004 advanced locomotion commands for the bot - strafing,
 * advanced turning, dodging...
 *
 * @author Michal 'Knight' Bida
 */
public class AdvancedLocomotion extends SimpleLocomotion
{
  
        /**
         * Makes the bot to move through first location to second location (may be 
         * specified directly or some ILocated object may be supplied - carefull with objects traversability).
         * Usage is when you want to have your bot to move really smooth. Where is the 
         * problem? If you would want to achive the same thing with 2 moveTo functions
         * (first move to location1, when there move to location2), there may be a 
         * little lag - you have to check if you are already at first location and etc.
         * This function can solve this problem as the check is done in UnrealScript.
         * 
         * (issues GB MOVE command)
         * 
         * @param firstLocation First location we will go through.
         * @param secondLocation Second location we will go to (after reaching first).
         * 
         * @see moveContinuous()
         */
        public void moveAlong(ILocated firstLocation, ILocated secondLocation)
        {
            Move moveAlong = new Move();
            
            moveAlong.setFirstLocation(firstLocation.getLocation());
            moveAlong.setSecondLocation(secondLocation.getLocation());
            
            agent.getAct().act(moveAlong);
        }
        
        /**
         * This makes the bot to run straight ahead continuously. Will stop when other
         * move command is issued - stopMovement, strafeTo, moveTo, moveAlong even turn commands 
         * will interrupt this.
         * 
         * (issues GB CMOVE command)
         * 
         * @see moveAlong(ILocated, ILocated)
         * 
         */
        public void moveContinuos()
        {
            agent.getAct().act(new ContinuousMove());
        }
        
    
        /** 
         * Makes the bot to move to location while looking at focusLocation. 
         * (issues GB STRAFE command) 
         * 
         * @param location Location we will strafe to.
         * @param focusLocation Location we will look at while strafing.
         * 
         * @see strafeTo(ILocated, UnrealId)
         */
        public void strafeTo(ILocated location, ILocated focusLocation)
        {
        	Move move = new Move().setFirstLocation(location.getLocation()).setFocusLocation(focusLocation.getLocation());
            agent.getAct().act(move);
        }               
        
        /** 
         * Makes the bot to move at location, while looking at focus object.
         * Note that when you support focus object, the bot will update his focus 
         * (place he is looking at) according to focus object location (this will be
         * provided by GB UnrealScript code).
         * Usefull when you want to track some player position while moving somewhere else.
         * (issues GB STRAFE command) 
         * 
         * @param location Location we will strafe to.
         * @param focus Object with UrealId. We will look at this location while strafing. We will update our focus location according to the current position of this obejct in UT.
         * 
         * @see strafeTo(ILocated, ILocated)
         * 
         * @todo To check if supported object is also ILocated? see below
         */
        public void strafeTo(ILocated location, UnrealId focus)
        {            
        	Move move = new Move().setFirstLocation(location.getLocation()).setFocusTarget(focus);
            //TODO: To check if this object is also ILocated?  
            //How this could be done? We need to check if supported IWorldObject
            //implements interface ILocated
            /*
            ILocated tmpILocatedCheck;
            if (tmpILocatedCheck.getClass() == focus.getClass().getInterfaces()[0])
            {
            
            }*/
            agent.getAct().act(move);            
        }           
        
        /** 
         * Makes the bot to double jump instantly (issues GB JUMP command) 
         * 
         * @todo How to convince javadoc see to link to method in super class
         * @see jump()
         * @see dodge(Vector3d)
         */
        public void doubleJump()
        {
            Jump jump =  new Jump();
            jump.setDoubleJump(true);
            agent.getAct().act(jump);           
        }
        
        /** 
         * Makes the bot to dodge in the selected direction (this is in fact 
         * single jump that is executed to selected direction). 
         * (issues GB DODGE command) 
         * 
         * @param direction Vector (that will be normalized) that specifies direction of the jump.
         * 
         * @see jump()
         * @see doubleJump()
         */
        public void dodge(Vector3d direction)
        {
            agent.getAct().act(new Dodge(direction));
        }
        
        /**
         * Sets the speed multiplier for the bot. By this number the bots default
         * speed will be multiplied by.
         * (issues GB CONF command)
         * 
         * @todo run ant script to get new GB commands updates and finish impl.
         * @param speedMultiplier Ranges from 0.1 to 2 (max may be set in ini in [RemoteBot] MaxSpeed)         
         */
        public void setSpeed(double speedMultiplier)
        {
            Configuration configure = new Configuration();
            //TODO: set the conf. attr.
            agent.getAct().act(configure);
        }
        
	/**
	 * 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.
	 */         
        public AdvancedLocomotion(AbstractUT2004Bot agent, Logger log)
	{
		super(agent, log);
                
	}
        
}