#include "stopLightBlinker.h"
#include <mechButton.h>

// The turn signal up 3 seconds after green,
// stays on for 3 seconds, 
// then blinks for 5 seconds together with green (in sync with green),
// before switching back to yellow.
//
// ADDED car wating button with flasher to control the turn signal.
//

#define RED_PIN         8
#define YELLOW_PIN      11
#define GREEN_PIN       9
#define WHITE_PIN       12
#define BUTTON_PIN      2
#define WAITING_PIN     3

#define GREEN_PULSE     500
#define WHITE_PULSE     GREEN_PULSE
#define GREEN_ON_MS     6000
#define WHITE_DELAY_MS  GREEN_ON_MS - 3000

stopLightBlinker  redLight(RED_PIN,3000);
stopLightBlinker  yellowLight(YELLOW_PIN,3000);
stopLightBlinker  greenLight(GREEN_PIN,GREEN_ON_MS,5000,GREEN_PULSE,GREEN_PULSE*2);
stopLightBlinker  whiteLight(WHITE_PIN,3000,5000,WHITE_PULSE,WHITE_PULSE*2);
blinker           waiting(WAITING_PIN);
mechButton        carWaitBtn(BUTTON_PIN);

enum liteStates { redLt, greenLt, yellowLt };     // Our possible wait states.
liteStates  ourState;                             // Our current wait state.
timeObj     whiteTimer(WHITE_DELAY_MS,false);     // Our delay before white comes on timer.
bool        carWaiting;                           // Flag for telling us a car is waiting for the turn signal (white)



// Standard setup.
void setup() {

  carWaiting = false;                 // No car waiting now.
  carWaitBtn.setCallback(carClick);   // If a car hits the button we call this function.
  redLight.begin();                   // Fire up the red light.
  yellowLight.begin();                // Fire up the yellow light..
  greenLight.begin();                 // Green..
  whiteLight.begin();                 // White (turn)
  doRed();                            // Start in the red light on mode.
}


// Button has changed state, what do we do?
void carClick(void) {

  if (!carWaitBtn.trueFalse()) {    // If the button has been mashed down (grounded)..
    if (!carWaiting) {              // If there is not already a car wating..
      waiting.setOnOff(true);       // Turn on the flasher.
      carWaiting = true;            // Note we have a wating car.
    }
  }
}

// Just turns all the stop lights off. Not the waiting car light.
void allOff(void) {
  
  redLight.turnOff();
  yellowLight.turnOff();
  greenLight.turnOff();
  whiteLight.turnOff();
}


// Go into red light state.
void doRed(void) {

  allOff();           // Shut off the lights.
  redLight.start();   // Start the red light cycle.
  ourState = redLt;   // Note it.
}


// Go into green light state.
void doGreen(void) {

  allOff();               // Shut off the lights.
  greenLight.start();     // Start the green light cycle.
  if (carWaiting) {       // If a car is wating..
    whiteTimer.start();   // Start the delay timer for the white light.
  }
  ourState = greenLt;     // Note it.
}


// Go into yellow light state.
void doYellow(void) {

  allOff();               // Shut off the lights.
  yellowLight.start();    // Start the yellow light cycle.
  ourState = yellowLt;    // Note it.
}


// Run the world..
void loop() {
  
  idle();                           // Let the magic happen behind the scenes.
  switch(ourState) {                // Check the state we are in..
    case redLt      :               // Red light running.
      if (redLight.done()) {        // If the red light is through..
        doGreen();                  // Switch to green state.
      }
    break;
    case greenLt    :               // Green light running.
      if (whiteTimer.ding()) {      // If the white light timer has expired. (IE been activated.)..
        whiteTimer.reset();         // Reset the white timer.
        whiteLight.start();         // Start the white light cycle.
        carWaiting = false;         // Clear the car waiting flag.
        waiting.setOnOff(false);    // Shut off the car waiting binker.
      }
      if (greenLight.done()) {      // If the green light is complete..
        doYellow();                 // Goto yellow state.
      }
    break;
    case yellowLt   :               // Yellow light running.
      if (yellowLight.done()) {     // If the yellow light has run its course..
        doRed();                    // Switch to red light state.
      }
    break;
    default : doRed(); break;       // On error? Go to red light state.
  }
}