#include <Servo.h>  //Importing the servo library
Servo diverter;  //Making an instance for my servo used to divert the marbles to one path or the other
//defining inputs
const int lightMode = 4;
const int lightToggle = 6;
const int pathMode = 2;
const int pathToggle = 3;
//defining outputs
const int servoPosition = 5;
const int servoPowerRelay = 7;
const int motorPowerRelay = 8;
const int red = 10;
const int yellow = 11;
const int blue = 12;
const int green = 13;
// defining variables and constants
bool pathAuto = false;   //this will be reference to tell if pathing is in automatic or manual
bool lightAuto = false;  //this will be reference to tell if lighting is in automatic or manual
const int pathRate = 777;  // 4000 life too short //interval for switching paths when in automatic
const int lightRate = 166;  // 500 life too short //interval for switching LEDs when in automatic
bool pathA = true;  //one servo value found by trial and error to effectively path the marble
//const int pathB = false;  //the other servo value found by trial and error to effectively path the marble
//int path = pathA;      //holder for current path state
const int buttonPress = 300;  //this will be referenced as part of a software debounce
unsigned long currentMillis = 0;           //this will be used as an ever progressing timeline
unsigned long lightModeButtonMillis = 0;   //this will be referenced as part of a software debounce
unsigned long lightStateButtonMillis = 0;  //this will be referenced as part of a software debounce
unsigned long servoModeButtonMillis = 0;   //this will be referenced as part of a software debounce
unsigned long servoStateButtonMillis = 0;  //this will be referenced as part of a software debounce
unsigned long pathSwitched = 0;            // this will hold the time that the path last changed; used in automatic mode
unsigned long lightSwitched = 0;           // this will hold the time that the LED tower last changed; used in automatic mode
void setup() {
  Serial.begin(9600);
  pinMode(lightMode, INPUT_PULLUP);    //this will look for UI to switch between manual and automatic lighting
  pinMode(lightToggle, INPUT_PULLUP);  //this will look for UI to switch current light state when in manual
  pinMode(pathMode, INPUT_PULLUP);    //this will look for UI to switch between manual and automatic pathing
  pinMode(pathToggle, INPUT_PULLUP);  //this will look for UI to switch current path state when in manual
  diverter.attach(5);  //this will send one of two values to the servo for pathing control
  //these will set two pins to output and constant high as they're energizing the optoisolator on power relays
  pinMode(servoPowerRelay, OUTPUT);
  digitalWrite(servoPowerRelay, HIGH);
  pinMode(motorPowerRelay, OUTPUT);
  digitalWrite(motorPowerRelay, HIGH);
  //these will be the wires activating a battery of relays feeding the LED arrays
  pinMode(red, OUTPUT);
  pinMode(yellow, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(green, OUTPUT);
  //this sets up the two UI controlled systems in a default starting state so that an LED is lit and the servo is positioned properly in case the system was previously shut off
  //while the servo was mid move
  //delay(2000);
  diverter.write(0);
  digitalWrite(random(10, 14), HIGH);  //this selects a random LED output pin to activate
  //digitalWrite(blue, HIGH);
  //Serial.println("end of setup");
  //delay(5000);
}
void loop() {
  //this will take the current reading of millis and pass it as a placeholder and then run through the functions which are where the logic lies.
  //Serial.println("loop");
  currentMillis = millis();
  //Serial.println("currentMillis");
  switchLightMode();
  //Serial.println("lightMode");
  switchPathMode();
  //Serial.println("pathMode");
  changeLED();
  //Serial.println("ledChange");
  changePath();
  //Serial.println("pathChange");
}
void switchLightMode() {
  //this function debounces by referencing variables and when the button is pressed, changes the state of the lightAuto bool
  if (millis() - lightModeButtonMillis >= buttonPress) {
    if (digitalRead(lightMode) == LOW) {
      lightAuto = !lightAuto;
      lightModeButtonMillis = millis();
      Serial.print("light Mode  ");
      Serial.println(lightAuto ? "automatic" : "manual");     
      //delay(500);
    }
  }
}
void switchPathMode() {
  //this function debounces by referencing variables and when the button is pressed, changes the state of the lightAuto bool
  if (millis() - servoModeButtonMillis >= buttonPress) {
    if (digitalRead(pathMode) == LOW) {
      pathAuto = !pathAuto;
      servoModeButtonMillis = millis();
      Serial.print("pathMode ");
      Serial.println(pathAuto ? "automatic" : "manual");
      //delay(500);
    }
  }
}
void changeLED() {
  int theLED = 0;
  if (lightAuto == true) {
    //Serial.println("lightAuto == true");
    if (currentMillis - lightSwitched >= lightRate) {
      digitalWrite(red, LOW);
      digitalWrite(yellow, LOW);
      digitalWrite(blue, LOW);
      digitalWrite(green, LOW);
      digitalWrite(random(10, 14), HIGH);  //this selects a random LED output pin to activate
      lightSwitched = currentMillis;
    }
  } else {
    if (millis() - lightStateButtonMillis >= buttonPress) {
      if (digitalRead(lightToggle) == LOW) {
        digitalWrite(red, LOW);
        digitalWrite(yellow, LOW);
        digitalWrite(blue, LOW);
        digitalWrite(green, LOW);
        theLED = random(10, 14);
        digitalWrite(theLED, HIGH);  //this selects a random LED output pin to activate
        lightStateButtonMillis = millis();
        Serial.print("lightSwitch to ");
        Serial.println(theLED);
        //delay(500);
      }
    }
  }
}
void changePath() {
  if (pathAuto == true) {
//    Serial.println("pathMode auto");
    //delay(500);
    if (currentMillis - pathSwitched >= pathRate) {
      if (pathA == true) {
        diverter.write(0);
        pathA = false;
        pathSwitched = currentMillis;
        Serial.println("position 0");
      } else {
        diverter.write(20);
        pathA = true;
        pathSwitched = currentMillis;
        Serial.println("position 20");
      }
    }
  } else {
//    Serial.println("pathMode manual");
    //delay(500);
//    Serial.print("pathToggleValue:  ");
//    Serial.println(digitalRead(pathToggle));
    if (currentMillis - servoStateButtonMillis >= buttonPress) {
      if (digitalRead(pathToggle) == LOW) {
        if (pathA != true) {
          diverter.write(0);
          Serial.println("pathA is not true");
          pathA = true;
          servoStateButtonMillis = currentMillis;
          //delay(500);
        }
        else {
          diverter.write(20);
          Serial.println("pathA is true");
          pathA = false;
          servoStateButtonMillis = currentMillis;
          //delay(500);
        }
      }
    }
  }
}
        /*
        //if (millis() - servoStateButtonMillis >= buttonPress && digitalRead(pathToggle == LOW)){
        Serial.println("pathSwitchButton");
        delay(500);
        Serial.println(pathA);
        if (pathA != true) {
          Serial.println("if block");
          delay(500);
          diverter.write(0);
          pathA = true;
          servoStateButtonMillis = currentMillis;
          Serial.println(pathA);
        } else {
          Serial.println("else block");
          delay(500);
          diverter.write(20);
          pathA = false;
          servoStateButtonMillis = currentMillis;
          Serial.println(pathA);
        }
      }
    }
  }
} */light Mode
path Mode
light Toggle
path Toggle