// For GUI Developer
// You need to send following characters to perform an action
// Send character 'a' to actiavte servo
// Send character 'b' to de-actiavte servo
// Send character 'c' to activate/de-actiavte visible laser lights
// Send character 'd' to de-actiavte Horn Relay and LED

/////////////////////////////////////////////////////////////////

#include "Button2.h"  // Include button2 library to handle button presses
#include <Servo.h>

/////////////////////////////////////////////////////////////////

Button2 servoBtn;         // Button to engage Servo on button press
Button2 visibleLaserBtn;  // Button to turn on/off visible laser light
Button2 blowerRelayBtn;   // Button to turn on/off Blower Relay

Servo servo;

// Button Pins
const byte emergency_stop_btn = 2;     // (Don't Change it from 2) Emergency Stop button pin
const byte servo_btn_pin = 3;          // Servo button pin to activate/deactivate laser button
const byte visible_laser_btn_pin = 4;  // button pin to activate/deactivate visibl laser light
const byte blower_btn_pin = 5;         // Blower Relay Button Pin

// Define pin connections
const int visible_laser_led_pin = 6;  // When activated, a LED will be on constantly (VISIBLE LASER ON)
const int visible_laser_light_1 = 7;  // Visible Laser Light 1 Pin
const int visible_laser_light_2 = 8;  // Visible Laser Light 2 Pin
const int servo_pin = 9;
const int blower_relay_pin = 10;        // Blower Relay Pin
const int blower_led_pin = 11;          // Led Attached with Blower Relay
const int system_ready_led_pin = 12;    // Led pin for sysmte Ready
const int emergency_stop_led_pin = 14;  // We will use A0 pin (led if emergency stop is pressed)
const int cleaning_laser_led_pin = 15;  // We will use A1 pin (Cleaning Laser Cycle Led pin)
const int buzzer_pin = 16;              // We will use A2 pin (Buzzer Pon)

// State variables
bool servo_active = false;
bool visible_laser_state = false;
bool blower_state = false;
volatile bool emergency_stop = false;  // Mark as volatile for ISR use

volatile unsigned long emergencyBtnPressTime = 0;  // Variable that hold the time when emergency button was pressed to avoid debounce


// Define servo angles
int initial_angle = 90;
int press_angle = 45;

// Interrupt Service Routine (ISR) for emergency stop
void emergencyStopISR() {
  if ((millis() - emergencyBtnPressTime) > 500) {
    emergencyBtnPressTime = millis();  // Note emergency Button press time
    emergency_stop = !emergency_stop;  // Toggle emergency stop flag
  }
}
void setup() {
  Serial.begin(9600);
  delay(50);

  pinMode(visible_laser_light_1, OUTPUT);  // Set Light pin as output
  pinMode(visible_laser_light_2, OUTPUT);  // Set Light pin as output
  pinMode(visible_laser_led_pin, OUTPUT);  // Set Light pin as output
  pinMode(blower_relay_pin, OUTPUT);       // Set Blower Relay pin as output
  pinMode(blower_led_pin, OUTPUT);         // Set Blower LED Pin as output
  pinMode(system_ready_led_pin, OUTPUT);

  setVisibleLaserLightState(visible_laser_state);  // Set the visible laser state on lights
  setBlowerState(blower_state);

  servoBtn.begin(servo_btn_pin, INPUT_PULLUP);
  servoBtn.setClickHandler(handler);
  servoBtn.setDoubleClickHandler(handler);
  visibleLaserBtn.begin(visible_laser_btn_pin, INPUT_PULLUP);
  blowerRelayBtn.begin(blower_btn_pin, INPUT_PULLUP);
  visibleLaserBtn.setPressedHandler(visibleBtnChange);  // Add button press handler for visible laser button
  blowerRelayBtn.setPressedHandler(blowerBtnChange);    // Add button press handler for blower relay button

  // Initialize servo and pins
  servo.attach(servo_pin);
  servo.write(initial_angle);

  // Turn on system ready LED
  digitalWrite(system_ready_led_pin, HIGH);

  // Attach interrupt for the emergency stop button (assuming pin 3)
  attachInterrupt(digitalPinToInterrupt(emergency_stop_btn), emergencyStopISR, FALLING);
}
// Main Loop that will run continuously
void loop() {
  // If emergency stop is triggered, stop further actions
  if (emergency_stop) {
    digitalWrite(emergency_stop_led_pin, HIGH);  // Turn on emergency light
    // If any System is active deactivate it
    if (servo_active) {
      setServoRelatedComponents(initial_angle, LOW);  // Reset servo angle and turn off related components
      servo_active = false;
    }
    if (visible_laser_state) {
      visible_laser_state = !visible_laser_state;      // Change visible laser states
      setVisibleLaserLightState(visible_laser_state);  // Set the visible laser state on lights
    }
    if (blower_state) {
      blower_state = !blower_state;  // Toggle Blower state on button press
      setBlowerState(blower_state);  // Set the current blower state for blower relay and led
    }
    return;
  }
  digitalWrite(emergency_stop_led_pin, LOW);  // Turn off emergency light

  char incData;  // Create an empty character variable to store incoming data
  if (Serial.available() > 0) {
    incData = Serial.read();  // Check if we have any incoming data available
    switch (incData) {
      case 'a':
        if (servo_active == false) {  // Check if we received 'a' and previously servo was not active activate it
          servo_active = true;
          setServoRelatedComponents(press_angle, HIGH);  // Set servo to press angle and turn on related components
        }
        break;
      case 'b':
        if (servo_active == true) {                       // Check if we received 'b' and previously servo active, de-activate it
          setServoRelatedComponents(initial_angle, LOW);  // Reset servo angle and turn off related components
          servo_active = false;
        }
        break;
      case 'c':
        visible_laser_state = !visible_laser_state;      // Change visible laser states
        setVisibleLaserLightState(visible_laser_state);  // Set the visible laser state on lights
        break;
      case 'd':
        blower_state = !blower_state;  // Toggle Blower state on button press
        setBlowerState(blower_state);  // Set the current blower state for blower relay and led
        break;
    }
  }
  servoBtn.loop();         // keep checking state of servo button
  visibleLaserBtn.loop();  // keep checking state
  blowerRelayBtn.loop();   // keep checking state
}
void visibleBtnChange(Button2& btn) {
  Serial.println("Visible Btn pressed");
  visible_laser_state = !visible_laser_state;      // Change visible laser states
  setVisibleLaserLightState(visible_laser_state);  // Set the visible laser state on lights
}
void blowerBtnChange(Button2& btn) {
  Serial.println("Blower Btn pressed");
  blower_state = !blower_state;  // Toggle Blower state on button press
  setBlowerState(blower_state);  // Set the current blower state for blower relay and led
}
void setVisibleLaserLightState(bool state) {
  digitalWrite(visible_laser_light_1, state);  // Get the state and set it on visible laser light
  digitalWrite(visible_laser_light_2, state);  // Get the state and set it on visible laser light
  digitalWrite(visible_laser_led_pin, state);  //When activated, a LED will be on constantly (VISIBLE LASER ON)
}
void setBlowerState(bool state) {
  digitalWrite(blower_relay_pin, state);
  digitalWrite(blower_led_pin, state);
}
void setServoRelatedComponents(int servoAngle, bool state) {
  servo.write(servoAngle);                      // Set servo angle according to button press
  digitalWrite(cleaning_laser_led_pin, state);  // Set laser led state according to button press for servo
  digitalWrite(buzzer_pin, state);              // Set buzzer state according to button press for servo
}
/////////////////////////////////////////////////////////////////

void handler(Button2& btn) {  // This handler is used to handl single and double button press for servo
  switch (btn.getType()) {
    case single_click:
      setServoRelatedComponents(initial_angle, LOW);  // Reset servo angle and turn off related components
      servo_active = false;
      break;
    case double_click:
      servo_active = true;
      setServoRelatedComponents(press_angle, HIGH);  // Set servo to press angle and turn on related components
      break;
    case empty:
      return;
  }
}
/////////////////////////////////////////////////////////////////