#include <LiquidCrystal_I2C.h>
#include <Wire.h>

const int button_start = 4;
const int potPin = A0;
const int tempPin = A1;
const int heaterPin = 6;

LiquidCrystal_I2C lcd(0x27, 16, 2);

const int pinA = 2;  // CLK
const int pinB = 3;  // DT
const int pinWS = 5;  // Switch

const int stepperStepPin = 7;  
const int stepperDirPin = 8;  

int target_temperature = 0;
int current_temperature = 0;
bool preheat_requested = false;
bool preheat_completed = false;
bool production_started = false;
bool production_paused = false;
unsigned long preheat_start_time = 0;
unsigned long buttonPressStart = 0;

int lastStateA = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;  // Debounce delay in milliseconds

double Kp = 1.0;
double Ki = 0.1;
double Kd = 0.1;
int previous_error = 0;
int integral = 0;

void setup() {
    lcd.init();
    lcd.backlight();

    pinMode(button_start, INPUT_PULLUP);
    pinMode(heaterPin, OUTPUT);
    pinMode(pinA, INPUT_PULLUP);
    pinMode(pinB, INPUT_PULLUP);
    pinMode(pinWS, INPUT_PULLUP);
    pinMode(stepperStepPin, OUTPUT);
    pinMode(stepperDirPin, OUTPUT);

    digitalWrite(heaterPin, LOW);

    lcd.print("Filament maker V1");
    delay(2000);
    lcd.clear();
    lcd.print("Turn knob to set");
    lcd.setCursor(0, 1);
    lcd.print("Press to preheat");

    Serial.begin(9600);
}

void loop() {
    int currentStateA = digitalRead(pinA);

    if (currentStateA != lastStateA) {
        if ((millis() - lastDebounceTime) > debounceDelay) {
            if (digitalRead(pinB) != currentStateA) {
                target_temperature += 5;
            } else {
                target_temperature -= 5;
            }
            target_temperature = constrain(target_temperature, 0, 260);
            Serial.println(target_temperature);

            lcd.clear();
            lcd.print("Temp: " + String(target_temperature) + " C");
            lcd.setCursor(0, 1);
            lcd.print("Press to set     ");
        }
        lastDebounceTime = millis();
    }
    lastStateA = currentStateA;

    if (digitalRead(pinWS) == LOW && !preheat_requested) {
        preheat_requested = true;
        preheat_start_time = millis();
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Preheating...");
    }

    current_temperature = analogRead(tempPin);

    if (preheat_requested && !preheat_completed) {
        unsigned long preheat_duration = millis() - preheat_start_time;

        if (preheat_duration < 5000) {
            lcd.setCursor(0, 1);
            lcd.print("Current Temp: " + String(current_temperature) + " C");
        } else {
            preheat_completed = true;
            scrollUntilButtonPressed("Preheat Done", 0);
            lcd.setCursor(0, 1);
            lcd.print("Press to start prod.");
        }
    } else if (preheat_completed && !production_started) {
        if (digitalRead(pinWS) == LOW) {
            production_started = true;
            scrollUntilButtonPressed("Starting production", 0);
            startStepper();
        }
    } else if (production_started && !production_paused) {
        if (digitalRead(pinWS) == LOW) {
            production_paused = true;
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Production paused");
        }
    } else if (production_paused) {
        if (digitalRead(pinWS) == LOW) {
            if (buttonPressStart == 0) {
                buttonPressStart = millis(); // start the timer
            } else if (millis() - buttonPressStart > 3000) {  // 3 seconds passed
                lcd.clear();
                lcd.setCursor(0, 0);
                lcd.print("Production stopped");
                stopStepper();  // Stop the stepper motor
                production_started = false;
                production_paused = false;
            }
        } else {
            buttonPressStart = 0;  // reset the timer
        }
    }
}

void startStepper() {
    digitalWrite(stepperDirPin, HIGH);  // Set direction (HIGH or LOW)
    for (int i = 0; i < 200; i++) {
        digitalWrite(stepperStepPin, HIGH);
        delayMicroseconds(1000);  // Speed of rotation
        digitalWrite(stepperStepPin, LOW);
        delayMicroseconds(1000);
    }
}

void stopStepper() {
    digitalWrite(stepperStepPin, LOW);
}

void scrollUntilButtonPressed(String text, int row) {
    if (text.length() <= 16) {
        lcd.setCursor((16 - text.length()) / 2, row);  // Centering text
        lcd.print(text);
        while (digitalRead(pinWS) == HIGH);  // Wait until button is pressed
        return;
    }

    text = "                " + text + "                ";
    int positionCounter = 0;
    while (digitalRead(pinWS) == HIGH) {
        lcd.setCursor(0, row);
        lcd.print(text.substring(positionCounter, positionCounter + 16));
        delay(300);  // Adjust speed of scrolling
        positionCounter++;
        if (positionCounter > text.length() - 16) positionCounter = 0;  // Reset scrolling
    }
}