const int START_STOP_BUTTON_PIN = 2;
const int DECREASE_BUTTON_PIN = 3;
const int INCREASE_BUTTON_PIN = 4;

const int IN1 = 8;
const int IN2 = 9;
const int IN3 = 10;
const int IN4 = 11;

enum State {
  IDLE,
  MOTOR_GATE_ON,
  MOTOR_OFF_GATE_ON,
  GATE_OFF
};

enum TimingMode {
  LOW_MODE,
  MEDIUM_MODE,
  HIGH_MODE
};

const unsigned long TIMING_MODES[3][3] = {
  {5000, 2000, 2000},  // LOW_MODE
  {6000, 2500, 3000},  // MEDIUM_MODE
  {7000, 3000, 4000}   // HIGH_MODE
};

volatile bool isRunning = false;
State currentState = IDLE;
TimingMode currentTimingMode = LOW_MODE;
unsigned long stateStartTime = 0;

volatile bool startStopButtonPressed = false;
volatile bool increaseButtonPressed = false;
volatile bool decreaseButtonPressed = false;

void setup() {
  pinMode(START_STOP_BUTTON_PIN, INPUT_PULLUP);
  pinMode(INCREASE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(DECREASE_BUTTON_PIN, INPUT_PULLUP);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  
  attachInterrupt(digitalPinToInterrupt(START_STOP_BUTTON_PIN), startStopInterrupt, FALLING);
  attachInterrupt(digitalPinToInterrupt(DECREASE_BUTTON_PIN), decreaseInterrupt, FALLING);
  attachInterrupt(digitalPinToInterrupt(INCREASE_BUTTON_PIN), increaseInterrupt, FALLING);
  
  stopMachineAndGate();
  
  Serial.begin(9600);
  Serial.println("System initialized. Press the start/stop button to begin.");
  printTimingMode();
}

void loop() {
  handleButtons();
  
  if (isRunning) {
    runStateMachine();
  }
}

void startStopInterrupt() {
  startStopButtonPressed = true;
}

void increaseInterrupt() {
  increaseButtonPressed = true;
}

void decreaseInterrupt() {
  decreaseButtonPressed = true;
}

void handleButtons() {
  if (startStopButtonPressed) {
    startStopButtonPressed = false;
    isRunning = !isRunning;
    if (isRunning) {
      currentState = MOTOR_GATE_ON;
      stateStartTime = millis();
      Serial.println("Machine started");
    } else {
      stopMachineAndGate();
      Serial.println("Machine stopped");
    }
  }
  
  if (increaseButtonPressed) {
    increaseButtonPressed = false;
    currentTimingMode = static_cast<TimingMode>((currentTimingMode + 1) % 3);
    printTimingMode();
  }
  
  if (decreaseButtonPressed) {
    decreaseButtonPressed = false;
    if (currentTimingMode == LOW_MODE) {
      currentTimingMode = HIGH_MODE;
    } else {
      currentTimingMode = static_cast<TimingMode>(currentTimingMode - 1);
    }
    printTimingMode();
  }
}

void runStateMachine() {
  unsigned long currentTime = millis();
  
  switch (currentState) {
    case MOTOR_GATE_ON:
      digitalWrite(IN1, HIGH);  // Motor forward
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);  // Gate on
      digitalWrite(IN4, LOW);
      if (currentTime - stateStartTime >= TIMING_MODES[currentTimingMode][0]) {
        currentState = MOTOR_OFF_GATE_ON;
        stateStartTime = currentTime;
      }
      break;
      
    case MOTOR_OFF_GATE_ON:
      digitalWrite(IN1, LOW);   // Motor stop
      digitalWrite(IN2, LOW);
      // Gate remains on
      if (currentTime - stateStartTime >= TIMING_MODES[currentTimingMode][1]) {
        currentState = GATE_OFF;
        stateStartTime = currentTime;
      }
      break;
      
    case GATE_OFF:
      digitalWrite(IN3, LOW);  // Gate off
      digitalWrite(IN4, LOW);
      if (currentTime - stateStartTime >= TIMING_MODES[currentTimingMode][2]) {
        currentState = MOTOR_GATE_ON;
        stateStartTime = currentTime;
      }
      break;
      
    default:
      break;
  }
}

void stopMachineAndGate() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  currentState = IDLE;
}

void printTimingMode() {
  Serial.print("Timing mode changed to: ");
  switch (currentTimingMode) {
    case LOW_MODE:
      Serial.println("Low");
      break;
    case MEDIUM_MODE:
      Serial.println("Medium");
      break;
    case HIGH_MODE:
      Serial.println("High");
      break;
  }
}