import jade.core.Agent;
import jade.core.AID;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.core.behaviours.SimpleBehaviour;
import java.util.*;

public class RunRobotBehaviour extends SimpleBehaviour {
	
	//AID of the ServerAgent
	private AID server;
		
	//counter for move actions
	private int actionCount, moveCount, turnCount, sensorCount;
	
	//Queue for actions waiting to be executed
	private Vector moveWaitingQueue, turnWaitingQueue, actionWaitingQueue;
	
	
	
	public RunRobotBehaviour(RobotAgent robot, AID server) {
		
		super(robot);
		this.server = server;
		actionCount = 0;
		moveCount = 0;
		turnCount = 0;
		sensorCount = 0;
		actionWaitingQueue = new Vector();
		moveWaitingQueue = new Vector();
		turnWaitingQueue = new Vector();
	}
	
	
	
	
	public void action() {
		boolean suspended = ((RobotAgent)myAgent).suspended();
		boolean alive = ((RobotAgent)myAgent).isAlive();
		boolean actionState = ((RobotAgent)myAgent).getActionState();
		
				
		
		//Frage Queue nur dann ab, wenn der RobotAgent noch nicht
		//in Aktion getreten ist und am Leben ist und noch nicht
		//schlafen gelegt wurde
		if (!suspended && alive && !actionState && (actionCount > 0)) {
			
			String command = "";
			
			try {
				command = (String)actionWaitingQueue.firstElement();
						
				System.out.println("HIER: "+command);
				
		
				if (command.equals("Move")) {
					((RobotAgent)myAgent).setActionState(true);
					actionWaitingQueue.removeElementAt(0);
			
					int distance = new Integer(""+moveWaitingQueue.firstElement()).intValue();
					moveWaitingQueue.removeElementAt(0);
					int direction = new Integer(""+moveWaitingQueue.firstElement()).intValue();
					moveWaitingQueue.removeElementAt(0);
			
					myAgent.addBehaviour(new RobotMoveBehaviour((RobotAgent)myAgent, server, distance, direction, this));
				
				}
			
			
				if (command.equals("SimpleMove")) {
					((RobotAgent)myAgent).setActionState(true);
					actionWaitingQueue.removeElementAt(0);
			
					int distance = new Integer(""+moveWaitingQueue.firstElement()).intValue();
					int direction = ((RobotAgent)myAgent).getDirection();
				
					myAgent.addBehaviour(new RobotMoveBehaviour((RobotAgent)myAgent, server, distance, direction, this));
				
				}
			
			
				if (command.equals("Turn")) {
					((RobotAgent)myAgent).setActionState(true);
					actionWaitingQueue.removeElementAt(0);
				
					int direction = new Integer(""+turnWaitingQueue.elementAt(0)).intValue();
					turnWaitingQueue.removeElementAt(0);
				
					myAgent.addBehaviour(new RobotTurnBehaviour((RobotAgent)myAgent, server, direction, this));
				}
			
			
				if (command.equals("Touch")) {
				
					((RobotAgent)myAgent).setActionState(true);
					actionWaitingQueue.removeElementAt(0);
								
					myAgent.addBehaviour(new RobotSensorBehaviour((RobotAgent)myAgent, server, "touch", this));
				}
			
			
				if (command.equals("Metall")) {
				
					((RobotAgent)myAgent).setActionState(true);
					actionWaitingQueue.removeElementAt(0);
								
					myAgent.addBehaviour(new RobotSensorBehaviour((RobotAgent)myAgent, server, "metall", this));
				}
			
			
				if (command.equals("Optic")) {
				
					((RobotAgent)myAgent).setActionState(true);
					actionWaitingQueue.removeElementAt(0);
								
					myAgent.addBehaviour(new RobotSensorBehaviour((RobotAgent)myAgent, server, "optic", this));
				}
			
			
				if (command.equals("Infra")) {
				
					((RobotAgent)myAgent).setActionState(true);
					actionWaitingQueue.removeElementAt(0);
								
					myAgent.addBehaviour(new RobotSensorBehaviour((RobotAgent)myAgent, server, "infra", this));
				}
			
			}  catch(Exception e) { }
		}
		
		
		
		//ensures that if the robot is suspended or killed, its move actions are reset;
		//for that reason, the moveWaitingQueue is cleared in that case;
		//as a consequence, incomming move requests from RobotAgent are ignored
		if (suspended || !alive) {
			actionWaitingQueue = new Vector();
			moveWaitingQueue = new Vector();
			turnWaitingQueue = new Vector();
		}		
		block();
	}
	
	
	
	
	public boolean done() {
		return false;
	}
	
	
	
	
	//this method finally invokes one simple move action
	//if moveCount is > 0
	public void move(int distance, int direction) {		
		actionCount++;
		moveCount++;
		actionWaitingQueue.addElement("Move");
		moveWaitingQueue.addElement(""+distance);
		moveWaitingQueue.addElement(""+direction);
		action();
		
		System.out.println("MOVE-QUEUE WURDE ERWEITERT");
	}
	
	
	//method move with only one parameter: distance
	public void move(int distance) {		
		actionCount++;
		moveCount++;
		actionWaitingQueue.addElement("SimpleMove");
		moveWaitingQueue.addElement(""+distance);
		moveWaitingQueue.addElement(""+distance);
		action();
		
		System.out.println("MOVE-QUEUE WURDE ERWEITERT (SimpleMove)");
	}
	
	
	//this method finally invokes one simple touch sensor action
	public void touch() {
		actionCount++;
		sensorCount++;
		actionWaitingQueue.addElement("Touch");
		action();
		
		System.out.println("SENSOR-QUEUE WURDE ERWEITERT");
	}
	
	
	// this method finally invokes one simple humidity sensor action
	public void humidity() {
		actionCount++;
		sensorCount++;
		actionWaitingQueue.addElement("Humidity");
		action();
		
		System.out.println("SENSOR-QUEUE WURDE ERWEITERT");
	}
	
	
	//this method finally invokes one simple metal sensor action
	public void metall() {
		actionCount++;
		sensorCount++;
		actionWaitingQueue.addElement("Metall");
		action();
		
		System.out.println("SENSOR-QUEUE WURDE ERWEITERT");
	}
	
	
	//this method finally invokes one simple optic sensor action
	public void optic() {
		actionCount++;
		sensorCount++;
		actionWaitingQueue.addElement("Optic");
		action();
		
		System.out.println("SENSOR-QUEUE WURDE ERWEITERT");
	}
	
	
	//this method finally invokes one simple infra-red sensor action
	public void infraRed() {
		actionCount++;
		sensorCount++;
		actionWaitingQueue.addElement("Infra");
		action();
		
		System.out.println("SENSOR-QUEUE WURDE ERWEITERT");
	}
	
	
	//this method finishes one simple sensor action
	//in decrementing sensorCount
	public void finishSensor() {
		sensorCount--;
		actionCount--;
		((RobotAgent)myAgent).setDataStore(true);
	}
	
	
	//this method finishes one simple move action
	//in decrementing moveCount
	public void finishMove() {
		moveCount--;
		actionCount--;
	}
	
	
	//this method invokes one simple turn action
	//if turnCount is > 0
	public void turn(int direction) {		
		actionCount++;
		turnCount++;
		actionWaitingQueue.addElement("Turn");
		turnWaitingQueue.addElement(""+direction);
		action();
		
		System.out.println("TURN-QUEUE WURDE ERWEITERT");
	}
	
	
	//this method finishes one simple turn action
	//in decrementing turnCount
	public void finishTurn() {
		turnCount--;
		actionCount--;
	}
		
}