#include <pt.h>
#include <OneButton.h>

// configure each button to be active when LOW
// with pullup resistors enabled
OneButton buttons[] = {
  OneButton(13, true, true),
  OneButton(12, true, true),
  OneButton(11, true, true),
  OneButton(10, true, true),
  OneButton(9, true, true),
};
const auto buttonsLen = sizeof(buttons) / sizeof(*buttons);

int state = 1;

static struct pt pt1, pt2, pt3, pt4;

void setup() {
  // set each button to call selectState() with a unique number
  // buttons are numbered from 0, states are numbered from 1
  // so an addition is necessary
  for (auto btn = 0; btn < buttonsLen; btn++) {
    buttons[btn].attachClick(selectState, btn + 1);
  }

  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  PT_INIT(&pt1);
  PT_INIT(&pt2);
  PT_INIT(&pt3);
  PT_INIT(&pt4);
}


void selectState(uint8_t newState) {
  state = newState;
}


void loop() {
  // poll the buttons
  for (auto btn = 0; btn < buttonsLen; btn++) {
    buttons[btn].tick();
  }

  switch (state) {
    case 1:
      SimpleBlink(&pt1);
      break;
    case 2:
      Pattern2(&pt2);
      break;
    case 3:
      Pattern3(&pt3);
      break;
    case 4:
      Pattern4(&pt4);
      break;
    case 5:
      break;
  }
}

static int SimpleBlink(struct pt *pt)
{
  static unsigned long lastTimeBlink = 0;
  PT_BEGIN(pt);

  while (1) {
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, HIGH);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, LOW); digitalWrite(6, LOW); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW);  digitalWrite(1, LOW);
  }
  PT_END(pt);
}

static int Pattern2(struct pt *pt)
{
  static unsigned long lastTimeBlink = 0;
  PT_BEGIN(pt);

  while (1) {

    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 100); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);


  }
  PT_END(pt);
}

static int Pattern3(struct pt *pt)
{
  static unsigned long lastTimeBlink = 0;
  PT_BEGIN(pt);

  while (1) {

    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 100); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 200); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    


  }
  PT_END(pt);
}

static int Pattern4(struct pt *pt)
{
  static unsigned long lastTimeBlink = 0;
  PT_BEGIN(pt);

  while (1) {

    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, HIGH); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, HIGH); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, HIGH); digitalWrite(4, LOW); digitalWrite(3, HIGH); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, HIGH); digitalWrite(6, HIGH); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, HIGH);  digitalWrite(1, LOW);
    lastTimeBlink = millis(); PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 400); 
    digitalWrite(7, HIGH); digitalWrite(6, LOW); digitalWrite(5, LOW); digitalWrite(4, LOW); digitalWrite(3, LOW); digitalWrite(2, LOW);  digitalWrite(1, LOW);
    

  }
  PT_END(pt);
}