// Pin Definitions
const int iPot = 12;
const int iOff = 2;
const int iPulse = 3;
const int iLow = 4;
const int iHigh = 5;
const int iPump = 7;
const int oPWM = 37; // White LED
const int oMAG = 39; // Blue LED
const int oPump = 21; // Green LED
const int oLight = 18; // Red LED

// Global Variables
int waitingTime = 5000; // Default waiting time in milliseconds (5 seconds)
bool isWipIntmRunning = false; // Flag to track if WipIntm function is running
unsigned long previousTime = 0; // Variable to store the previous time for checking elapsed time

// Default state: WipOffPark
int currentState = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("Hello, this is BoopWiper.");
  // Initialize input pins
  pinMode(iPot, INPUT);
  pinMode(iOff, INPUT_PULLUP);
  pinMode(iPulse, INPUT_PULLUP);
  pinMode(iLow, INPUT_PULLUP);
  pinMode(iHigh, INPUT_PULLUP);
  pinMode(iPump, INPUT_PULLUP);

  // Initialize output pins
  pinMode(oPWM, OUTPUT);
  pinMode(oMAG, OUTPUT);
  pinMode(oPump, OUTPUT);
  pinMode(oLight, OUTPUT);

  // Default state: all relays off (WipOffPark)
  digitalWrite(oPWM, LOW);
  digitalWrite(oMAG, LOW);
  digitalWrite(oPump, LOW);
  digitalWrite(oLight, LOW);
}

void loop() {
  // Read input states
  int offParkState = digitalRead(iOff);
  int intmState = digitalRead(iPulse);
  int loState = digitalRead(iLow);
  int hiState = digitalRead(iHigh);
  int pumpState = digitalRead(iPump);

  // Check if iPump is pressed to turn on oPump
  if (pumpState == LOW) {
    digitalWrite(oPump, HIGH);
    if (offParkState == LOW) {
      // If iPump is pressed in WipOffPark state, set oPWM to 40% duty cycle and turn on oMAG
      digitalWrite(oMAG, HIGH);
      analogWrite(oPWM, 102); // Set oPWM to 40% duty cycle
    }
  } else {
    digitalWrite(oPump, LOW);
    if (offParkState == LOW) {
      // If iPump is released in WipOffPark state, turn off oMAG and set oPWM to LOW
      digitalWrite(oMAG, LOW);
      digitalWrite(oPWM, LOW);
    }
  }

  // Check if WipIntm state needs to be exited
  if (currentState == 1 && isWipIntmRunning && intmState == HIGH) {
    isWipIntmRunning = false;
    digitalWrite(oMAG, LOW);
    Serial.println("Pulse ended...");
  }

  // Check input states and execute corresponding functions
  if (offParkState == LOW && pumpState == HIGH) {
    WipOffPark();
    currentState = 0; // Set current state to WipOffPark
  } else if (intmState == LOW) {
    if (!isWipIntmRunning) {
      WipIntm();
      currentState = 1; // Set current state to WipIntm
    }
  } else if (loState == LOW) {
    WipLo();
    currentState = 2; // Set current state to WipLo
  } else if (hiState == LOW) {
    WipHi();
    currentState = 3; // Set current state to WipHi
  } else {
    // Stop WipIntm function if no input is detected
    if (currentState == 1 && isWipIntmRunning) {
      isWipIntmRunning = false;
      Serial.println("Pulse is off again...");
      digitalWrite(oMAG, LOW);
    }
  }

  // Update waiting time based on potentiometer value
  int potValue = analogRead(iPot);
  waitingTime = map(potValue, 0, 4095, 5000, 30000); // 5 seconds to 30 seconds

  // Check if the waiting time has elapsed for WipIntm function
  if (currentState == 1 && isWipIntmRunning && millis() - previousTime >= waitingTime) {
    previousTime = millis(); // Update the previous time for the next waiting period
    Serial.println("Warpp??");
    digitalWrite(oMAG, HIGH);
    delay(1000);
    digitalWrite(oMAG, LOW);
  }
}

void WipOffPark() {
  Serial.println("I am now in off position, nothing will happen now!");
  digitalWrite(oLight, LOW);
  digitalWrite(oMAG, LOW);
  //analogWrite(oPWM, 102);
  delay(2000);
  analogWrite(oPWM, 0);
}

void WipIntm() {
  isWipIntmRunning = true; // Set the flag to indicate that WipIntm function is running
  // Serial.println("Pulse mode!");

  analogWrite(oPWM, 115);
  digitalWrite(oMAG, LOW);

  while (isWipIntmRunning) {
    // WipIntm function code
    int potValue = analogRead(iPot);
    waitingTime = map(potValue, 0, 4095, 5000, 30000); // Update waiting time based on potentiometer value

    unsigned long currentTime = millis();
    if (currentTime - previousTime >= waitingTime) {
      previousTime = currentTime;
      Serial.println("Wipe...");
      digitalWrite(oMAG, HIGH);
      delay(1000);
      digitalWrite(oMAG, LOW);
    }
    
    // Check if iPump is pressed during WipIntm
    int pumpState = digitalRead(iPump);
    if (pumpState == LOW) {
      // Serial.println("Pulse and pumping");
      digitalWrite(oMAG, HIGH); // Keep oMAG on
      digitalWrite(oPump, HIGH);
    } else {
      // Serial.println("Pulse and pump off");
      digitalWrite(oMAG, LOW); // Turn off oMAG when iPump is released
      digitalWrite(oPump, LOW);
      isWipIntmRunning = false;
    }
  }

  // isWipIntmRunning = false; // Reset the flag after the loop ends
  // Serial.println("Pulse ended...");
}

void WipLo() {
  // Serial.println("Wipers are in low speed! 40% DutyCycle");
  analogWrite(oPWM, 102); // Set oPWM to 40% duty cycle
  digitalWrite(oMAG, HIGH);
  digitalWrite(oLight, LOW);
  delay(20);
}

void WipHi() {
  // Serial.println("Wipers are now in high speed! 75% Duty Cycle");
  analogWrite(oPWM, 200);
  digitalWrite(oMAG, HIGH);
  digitalWrite(oLight, HIGH);
  delay(20);
}
