#include <idlers.h>
#include <timeObj.h>


#define YELLOW  A1
#define BLUE    A2
#define ANALOG_MAX  200


int Led[] = {11, 10, 9, 8, 7, 6, 5, 4};

int JumpTime = 1000; // in millis
int WAITtime = 5000; // in millis

class oneShot :   timeObj,
                  public idler {

   public:
                  oneShot(float shotTime,int outPin=13);
   virtual        ~oneShot(void);

            void  fire(void);
   virtual  void  idle(void);

   protected:
            enum   oneShotStates  { sitting, running };

            oneShotStates  mOurState;
            int            mOutPin;
            bool           mInit;
};


// Our constructor. All thie bits we can adjust at creation time.
oneShot::oneShot(float shotTime,int outPin)
   : timeObj(shotTime,false),              // Set up our pulse timer.
   idler() {                               // Set up our idler class things.

   mOutPin        = outPin;                // Save our output pin number.
   mOurState      = sitting;               // Set our initial state.
   mInit          = false;
}

oneShot::~oneShot(void) { }


// On with the LED. Setup of not already.
void oneShot::fire(void) {

   if (!mInit) {
     pinMode(mOutPin,OUTPUT);                                // Setup our output pin.
     hookup();                                               // Hook into the idler queue.
     mInit = true;
   }
   digitalWrite(mOutPin,true);                       // Make sure its not in the triggered state.
   start();                                       // We start our timer.
   mOurState = running;                           // And our state is now running.
}



// What we do al day..
void oneShot::idle(void) {

   switch(mOurState) {
      case sitting  :  break;                             // We are sitting, waiting for fire signal.
      case running   :                                     // We have an active pulse going. Waiting for the timer to expire.
         if (ding()) {                                     // If the timer has expired..
            digitalWrite(mOutPin,LOW);                     // LED off.
             mOurState = sitting;                          // And our state is now running.
         }
      break;
   }
}


// *****************************************************************

oneShot LED1(WAITtime,11);
oneShot LED2(WAITtime,10);
oneShot LED3(WAITtime,9);
oneShot LED4(WAITtime,8);
oneShot LED5(WAITtime,7);
oneShot LED6(WAITtime,6);
oneShot LED7(WAITtime,5);
oneShot LED8(WAITtime,4);

timeObj yellowTimer(JumpTime,false);
timeObj blueTimer(JumpTime,false);

enum states { sitting, firingYelllow, firingBlue };

states  state;
int     yIndex;
int     bIndex;

void setup() {
  
  yIndex = -1;
  bIndex = -1;
  state = sitting;
}


void doFiringYellow(void) {

  if (yIndex<0) {
    LED8.fire();
    yIndex = 1;
    yellowTimer.start();
  } else if (yellowTimer.ding()) {
    yellowTimer.start();
    switch (yIndex) {
      case 1 :
        LED7.fire();
        yIndex++;
      break;
      case 2 :
        LED6.fire();
        yIndex++;
      break;
      case 3 :
        LED5.fire();
        yIndex++;
      break;
      case 4 :
        LED4.fire();
        yIndex++;
      break;
      case 5 :
        LED3.fire();
        yIndex++;
      break;
      case 6 :
        LED2.fire();
        yIndex++;
      break;
      case 7 :
        LED1.fire();
        yellowTimer.reset();
        yIndex = -1;
        state = sitting;
      break;
    }
  }
}


void doFiringBlue(void) {

  if (bIndex<0) {
    blueTimer.start();
    LED1.fire();
    bIndex = 1;
  } else if (blueTimer.ding()) {
    blueTimer.start();
    switch (bIndex) {
      case 1 :
        LED2.fire();
        bIndex++;
      break;
      case 2 :
        LED3.fire();
        bIndex++;
      break;
      case 3 :
        LED4.fire();
        bIndex++;
      break;
      case 4 :
        LED5.fire();
        bIndex++;
      break;
      case 5 :
        LED6.fire();
        bIndex++;
      break;
      case 6 :
        LED7.fire();
        bIndex++;
      break;
      case 7 :
        LED8.fire();
        blueTimer.reset();
        bIndex = -1;
        state = sitting;
      break;
    }
  }
}


void loop() {

  idle();
  switch (state) {
    case sitting :
      if (analogRead(YELLOW)>ANALOG_MAX) {
        state = firingYelllow;
      } else if (analogRead(BLUE)>ANALOG_MAX) {
        state = firingBlue;
      }
    break;
    case firingYelllow :
      doFiringYellow();
    break;
    case firingBlue :
      doFiringBlue();
    break;
  }

}