import josx.platform.rcx.*; 
import java.util.Vector;

public class Brain 
{ 

//listeners for sensors
LeftBumper lb;
RightBumper rb;
LightSensor ls;
ButtonSensor bs;

//memory and current index
public static int memory[] ;
public static int goalachieve[];
public static int discourage[];
public static int ind;
public static int indG;
public static int indD;
public  static int currentG;

//events constants

// 4 actions
public static final int RightForward =0;
public static final int LeftForward = 1;
public static final int LeftBackward = 2;
public static final int RightBackward = 3;

// 3 sensors
public static final int RightBumper = 26;
public static final int LeftBumper = 27;
public static final int Food = 28;

	//all the events are added to memory
	public static void addToMemory(int event)
	{
		if(ind > 45)  ind = 0;
		memory[ind] = event;
		ind++;
	}
	
	//the tank needs to think what caused it to get food
	public static void think()
	{
			//copy over the history which caused the achievement
			int tempi = ind;
			indG = 0;
			while(tempi >=0 && memory[tempi] <= 3)
			{
				goalachieve[indG] = memory[tempi];
				indG++;
				tempi--;
			}
			currentG = indG;
			ind = 0;
	}

	public static void discourage()
	{
		//forget the past, it does not serve your goal
		//undo what i did which was discouraged
		
			Sound.systemSound(true, 2);
			int tempi = ind;
			indD = 0;
			while(tempi >=0 && memory[tempi] <= 3)
			{
				discourage[indD] = memory[tempi];
				indD++;
				tempi--;
			}
			currentG = indD;
			ind = 0;
			indG = 0;
	}

	public Brain()
	{
		lb = new LeftBumper();
		rb = new RightBumper();
		ls = new LightSensor();
		bs = new ButtonSensor();
		memory = new int[40];
		goalachieve = new int[40];
		discourage = new int[40];
		ind = 0;	
		indG =0;	
		indD = 0;
		currentG = 0;
	}

	public static void leftForward()
	{
	    Motor.A.forward(); 
	    try { Thread.sleep(1000); } 
	    catch (InterruptedException ie) {} 
	    Motor.A.stop(); 
		addToMemory(LeftForward);
	}

	public static void rightForward()
	{
	    Motor.C.forward(); 
	    try { Thread.sleep(1000); } 
	    catch (InterruptedException ie) {} 
	    Motor.C.stop(); 
		addToMemory(RightForward);
	}
	

	public static void leftBackward()
	{
	    Motor.A.backward(); 
	    try { Thread.sleep(1000); } 
	    catch (InterruptedException ie) {} 
	    Motor.A.stop(); 
		addToMemory(LeftBackward);
	}

	public static void rightBackward()
	{
	    Motor.C.backward(); 
	    try { Thread.sleep(1000); } 
	    catch (InterruptedException ie) {} 
	    Motor.C.stop(); 
		addToMemory(RightBackward);
	}

	//default action
	public static void reflexTouch()
	{
	    Motor.A.backward(); 
	    Motor.C.backward(); 
	    try { Thread.sleep(4000); } 
	    catch (InterruptedException ie) {} 
	    Motor.A.stop(); 
	    Motor.C.stop(); 		
	}

	public static void doWhat()
	{
			int dow = 0;
			if( (indG == 0 && indD==0) || currentG  < 0)
			{
				currentG = 0;
				indG = 0;
				indD = 0;
				 dow = (int) (4* Math.random());
				if(dow == Brain.RightForward) Brain.rightForward();
				if(dow == Brain.LeftForward) Brain.leftForward();
				if(dow == Brain.RightBackward) Brain.rightBackward();
				if(dow == Brain.LeftBackward) Brain.leftBackward();

				
			}
			else if(indG > 0)
			{
				currentG--;
				if(currentG == 0) {indG = 0; ind = 0; indD=0; }
				dow = goalachieve[currentG];
				if(dow == Brain.RightForward) Brain.rightForward();
				if(dow == Brain.LeftForward) Brain.leftForward();
				if(dow == Brain.RightBackward) Brain.rightBackward();
				if(dow == Brain.LeftBackward) Brain.leftBackward();

			}
			else if(indD > 0)
			{
				currentG--;
				if(currentG == 0) {indG = 0; ind = 0;  }
				dow = discourage[indD-currentG];
				if(dow == Brain.RightForward) Brain.rightBackward();
				if(dow == Brain.LeftForward) Brain.leftBackward();
				if(dow == Brain.RightBackward) Brain.rightForward();
				if(dow == Brain.LeftBackward) Brain.leftForward();
				if(currentG == indD) { indD=0;  }

			}

			    try { Thread.sleep(2000); } 
	     		    catch (InterruptedException ie) {} 

	}

  	public static void main(String[] args) { 
			Sensor.S1.setTypeAndMode (1,0x80);
			Sensor.S2.setTypeAndMode (3,0x80);
			Sensor.S3.setTypeAndMode (1,0x80);
			Sensor.S1.activate(); 
			Sensor.S2.activate(); 
			Sensor.S3.activate(); 


			Brain br = new Brain();
			while(true)
			{
				br.doWhat();				
			}
  	} 
} 


class LeftBumper implements SensorListener
{
	public LeftBumper()
	{
		Sensor.S1.addSensorListener(this);			
	}

	public void stateChanged(Sensor leftBumper, int oldValue, int newValue)
	{
		if(leftBumper.readBooleanValue() == true) 
		{
			Brain.reflexTouch();
			Brain.addToMemory(Brain.LeftBumper);

		}
	}

}

class RightBumper implements SensorListener
{
	public RightBumper()
	{
		Sensor.S3.addSensorListener(this);			
	}

	public void stateChanged(Sensor rightBumper, int oldValue, int newValue)
	{
		if(rightBumper.readBooleanValue() == true) 
		{
			Brain.reflexTouch();
			Brain.addToMemory(Brain.RightBumper);
		}
	}

}

class LightSensor implements SensorListener
{
	int lastStateTime = 0;
	public LightSensor()
	{
		Sensor.S2.addSensorListener(this);			
	}

	public void stateChanged(Sensor lightSensor, int oldValue, int newValue)
	{

		int tim1 = (int)System.currentTimeMillis() ;
		tim1 = tim1-2000;
		//if a black spot it identified double beep
		//thats food
		if(lightSensor.readRawValue()> 700 && tim1  > lastStateTime)
		{
			    try { Thread.sleep(200); } 
		    		catch (InterruptedException ie) {} 
	
			if(lightSensor.readRawValue()> 730 )
			{
			
				Sound.beep();
				lastStateTime = 	(int)System.currentTimeMillis() ;	
				Brain.think();	
			}
		}

		/*
		if(lightSensor.readRawValue() >685 && lightSensor.readRawValue() <710 && tim1  > lastStateTime)
		{
			    try { Thread.sleep(200); } 
		    		catch (InterruptedException ie) {} 		
			if(lightSensor.readRawValue() >690 && lightSensor.readRawValue() <700 )
			{	
				Sound.beep();
				Sound.beep();
				Sound.beep();
				lastStateTime = 	(int)System.currentTimeMillis() ;	
				Brain.discourage();	
			}
		}
		*/

		LCD.showNumber(lightSensor.readRawValue());

	}

}

class ButtonSensor implements ButtonListener
{
	public ButtonSensor()
	{
		Button.RUN.addButtonListener(this);

	}

	public void buttonPressed(Button b)
	{
		Brain.discourage();	
		LCD.showNumber(1);
	}

	public void buttonReleased(Button b)
	{

	}


}