#include <IRremote.h>
#define PIN_RECEIVER A0

int Lane1[] = {13,12,11}; // Lane 1 Red, Yellow and Green
int Lane2[] = {10,9,8};// Lane 2 Red, Yellow and Green
int Lane3[] = {7,6,5};// Lane 3 Red, Yellow and Green
int Lane4[] = {4,3,2};// Lane 4 Red, Yellow and Green
boolean task48aEnable;
boolean task24aEnable;
boolean task122aEnable;
boolean task16aEnable;
boolean task168aEnable0;
boolean task168aEnable;
boolean task168aEnable1;
boolean task168aEnable2;
boolean task168aEnable3;
boolean task168aEnable4;
boolean task168aEnable5;
boolean task168aEnable6;
unsigned long int runTask48a;
unsigned long int runLane1Green;
unsigned long int runLane3Yellow;
unsigned long int runLane3Green;
unsigned long int runLane4Yellow;
unsigned long int runLane4Green;
unsigned long int runLane2Yellow;
unsigned long int runLane2Green;
IRrecv receiver(PIN_RECEIVER);
decode_results results;      

void setup() 
{
  receiver.enableIRIn();
  for (int i = 0; i < 3; i++)
  {
    pinMode(Lane1[i], OUTPUT); 
    pinMode(Lane2[i], OUTPUT);
    pinMode(Lane3[i], OUTPUT);
    pinMode(Lane4[i], OUTPUT);
  }
}

void loop() 
{  
  
  if (receiver.decode()) 
  {
      translateIR();
      receiver.resume();  // Receive the next value
  }
  if(receiver.decodedIRData.command==168)//loop
  {
    if(task168aEnable0 == true)
    {
      Button1();// loop for lane1 yellow
    }
    if(task168aEnable == true and millis() > runLane1Green)
    {
      task48a();// loop for lane1 green
    }
    if(task168aEnable1 == true and millis() > runLane3Yellow)
    {
      Button2();//loop for lane3 yellow
    }
    if(task168aEnable2 == true and millis() > runLane3Green)
    {
      task24a();//loop for lane3 green
    }
    if(task168aEnable3 == true and millis() > runLane4Yellow)
    {
      Button3();//loop for lane4 yellow
    }
    if(task168aEnable4 == true and millis() > runLane4Green)
    {
      task122a();//loop for lane3 green
    }
    if(task168aEnable5 == true and millis() > runLane2Yellow)
    {
      Button4();//loop for lane2 yellow
    }
    if(task168aEnable6 == true and millis() > runLane2Green)
    {
      task16a();//loop for lane2 green
    }
  }
  if(task48aEnable == true and millis() > runTask48a)//button 1
  {
    if(receiver.decodedIRData.command==48)
    {
      task48a();
    }
  } 
  if( task24aEnable == true and millis() > runTask48a)//button 2
  {
    if(receiver.decodedIRData.command==24)
    {
      task24a();
    }
  }
  if( task122aEnable == true and millis() > runTask48a)//button 3
  {
    if(receiver.decodedIRData.command==122)
    {
      task122a();
    }
  } 
  if( task16aEnable == true and millis() > runTask48a)//button 4
  {
    if(receiver.decodedIRData.command==16)
    {
      task16a();
    }
  }
}
void task48a(){
       digitalWrite(Lane1[1], LOW);
       digitalWrite(Lane1[2], HIGH); //lane 1-Green
          task48aEnable = false;  // do not run this task again until enabled          
       if(receiver.decodedIRData.command==168)
       {
        task168aEnable = false;
        task168aEnable1 = true; 
       }   
}
void task24a(){
       digitalWrite(Lane3[1], LOW);
  	   digitalWrite(Lane3[2], HIGH); //lane 3-Green
          task24aEnable = false; // do not run this task again until enabled
       if(receiver.decodedIRData.command==168)
       {
        task168aEnable2 = false;
        task168aEnable3 = true; 
       } 
}
void task122a(){
       digitalWrite(Lane4[1], LOW);
  	   digitalWrite(Lane4[2], HIGH); //lane 4-Green
          task122aEnable = false;  // do not run this task again until enabled          
        if(receiver.decodedIRData.command==168)
       {
        task168aEnable4 = false;
        task168aEnable5 = true;
       } 
}
void task16a(){
       digitalWrite(Lane2[1], LOW);
  	   digitalWrite(Lane2[2], HIGH); //lane 2-Green
          task16aEnable = false;  // do not run this task again until enabled          
       if(receiver.decodedIRData.command==168)
       {
        task168aEnable6 = false;
        task168aEnable0 = true;
        runLane1Green = millis() + 3000;
        runLane3Yellow = millis() + 13000;
        runLane3Green = millis() + 16000;
        runLane4Yellow = millis() + 23000;
        runLane4Green = millis() + 26000;
        runLane2Yellow = millis() + 36000;
        runLane2Green = millis() + 39000; 
       } 
}
void PowerOff()
{
      digitalWrite(Lane1[0], LOW);
	    digitalWrite(Lane1[2], LOW);
	    digitalWrite(Lane1[1], LOW); 
	    digitalWrite(Lane3[1], LOW);
	    digitalWrite(Lane3[2], LOW);
  	  digitalWrite(Lane3[0], LOW); 
	    digitalWrite(Lane4[1], LOW);
	    digitalWrite(Lane4[2], LOW); 
  	  digitalWrite(Lane4[0], LOW); 
      digitalWrite(Lane2[1], LOW);
	    digitalWrite(Lane2[2], LOW);
  	  digitalWrite(Lane2[0], LOW);
}
void Button1()
{
      digitalWrite(Lane1[0], LOW);
	    digitalWrite(Lane1[2], LOW);
	    digitalWrite(Lane1[1], HIGH); //lane 1-Yellow
	    digitalWrite(Lane3[1], LOW);
	    digitalWrite(Lane3[2], LOW);
  	  digitalWrite(Lane3[0], HIGH); //lane 3-Red
	    digitalWrite(Lane4[1], LOW);
	    digitalWrite(Lane4[2], LOW); 
  	  digitalWrite(Lane4[0], HIGH); //lane 4-Red
	    digitalWrite(Lane2[1], LOW);
	    digitalWrite(Lane2[2], LOW);
  	  digitalWrite(Lane2[0], HIGH); //lane 2-red
      if(receiver.decodedIRData.command==168)
      {
        task168aEnable0 = false;
        task168aEnable = true;
      }
}
void Button2()
{
      digitalWrite(Lane4[1], LOW);
	    digitalWrite(Lane4[2], LOW); 
  	  digitalWrite(Lane4[0], HIGH);  //lane 4-Red
	    digitalWrite(Lane2[1], LOW);
	    digitalWrite(Lane2[2], LOW);
  	  digitalWrite(Lane2[0], HIGH);  //lane 2-Red   
      digitalWrite(Lane1[2], LOW);
	    digitalWrite(Lane1[1], LOW);
	    digitalWrite(Lane1[0], HIGH); 	//lane 1-Red	
	    digitalWrite(Lane3[0], LOW);
	    digitalWrite(Lane3[2], LOW);	
  	  digitalWrite(Lane3[1], HIGH);	//lane 3-Yellow
      if(receiver.decodedIRData.command==168)
      {
        task168aEnable1 = false;
        task168aEnable2 = true;
      }
}
void Button3()
{
      digitalWrite(Lane4[2], LOW); 
  	  digitalWrite(Lane4[0], LOW);
	    digitalWrite(Lane4[1], HIGH);  //lane 4-Yellow
	    digitalWrite(Lane2[1], LOW);
	    digitalWrite(Lane2[2], LOW);
  	  digitalWrite(Lane2[0], HIGH);  //lane 2-Red   
      digitalWrite(Lane1[2], LOW);
	    digitalWrite(Lane1[1], LOW);
	    digitalWrite(Lane1[0], HIGH); 	//lane 1-Red	
	    digitalWrite(Lane3[1], LOW);
	    digitalWrite(Lane3[2], LOW);	
  	  digitalWrite(Lane3[0], HIGH);	 //lane 3-Red
      if(receiver.decodedIRData.command==168)
      {
        task168aEnable3 = false;
        task168aEnable4 = true;
      }
}
void Button4()
{
      digitalWrite(Lane4[2], LOW); 
  	  digitalWrite(Lane4[1], LOW);
	    digitalWrite(Lane4[0], HIGH);  //lane 4-Red
	    digitalWrite(Lane2[0], LOW);
	    digitalWrite(Lane2[2], LOW);
  	  digitalWrite(Lane2[1], HIGH);  //lane 2-Yellow   
      digitalWrite(Lane1[2], LOW);
	    digitalWrite(Lane1[1], LOW);
	    digitalWrite(Lane1[0], HIGH); 	//lane 1-Red	
	    digitalWrite(Lane3[1], LOW);
	    digitalWrite(Lane3[2], LOW);	
  	  digitalWrite(Lane3[0], HIGH);	//lane 3-Red
      if(receiver.decodedIRData.command==168)
      {
        task168aEnable5 = false;
        task168aEnable6 = true;
      }
}
void translateIR()
{
  // Takes command based on IR code received
  switch (receiver.decodedIRData.command) {
    case 48:
    //Keypad button "1"     
         //Lane 1 - Green
      Button1();
	    task48aEnable = true; // this is a global boolean variable.
      runTask48a = millis() + 3000; // this is a global unsigned long int
      break; 
    case 24:
      //Keypad button "2"     
         //Lane 3 - Green
	    Button2();
  	  task24aEnable = true;
      runTask48a = millis() + 3000;   
      break;
    case 122:
      //Keypad button "3"     
          //Lane 4 - Green
	    Button3();
      task122aEnable = true;
      runTask48a = millis() + 3000;   
      break; 
    case 16:
      //Keypad button "4"     
         //Lane 2 - green     
      Button4();
      task16aEnable = true;
      runTask48a = millis() + 3000;
      break;
    case 162:
    //Power button
    // All Lane goes OFF
      PowerOff(); 
      break;
    case 168:
    //play button
    //loops continuesly
      PowerOff();
      task168aEnable0 = true;
      runLane1Green = millis() + 3000;
      runLane3Yellow = millis() + 13000;
      runLane3Green = millis() + 16000;
      runLane4Yellow = millis() + 23000;
      runLane4Green = millis() + 26000;
      runLane2Yellow = millis() + 36000;
      runLane2Green = millis() + 39000;
      break;
   }
}