//------------------------------- librarys ----------------------------------

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

//------------------------------- lcd ----------------------------------
LiquidCrystal_I2C lcd(0x27, 16, 2);

//------------------------------- ultrasonic ----------------------------------

const int pingPin = 8; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 7; // Echo Pin of Ultrasonic Sensor


//------------------------------- servo ----------------------------------
Servo snippers;
#define servo 6
#define openAngle 180
#define closedAngle 0

//------------------------------- input ----------------------------------

#define rightButton  2
#define leftButton 3
#define upButton 4
#define downButton 5
#define led 9
#define led2 10
#define led3 11
#define motor 12

//------------------------------- user settings ----------------------------------
unsigned int Length = 0;
unsigned int Quantity = 0;

//------------------------------- system settings ----------------------------------
int state = 0;
int incrementSpeed = 1;
int previousLength = 0;
int previousQuantity = 0;

long microsecondsToInches(long microseconds) {
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds) {
  return microseconds / 29 / 2;
}




void setup() {

  Serial.begin(9600);

  lcd.backlight();
  lcd.begin(16, 2);
  lcd.home ();


  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);
  //pinMode(Button, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(motor, OUTPUT);




  snippers.attach(servo);

  snippers.write(openAngle);

  delay(1000);


}

void loop() {

  //lcd.setCursor(0, 1);
  //lcd.print(Ultra() );


  if (!digitalRead(rightButton)) {
    if (state == 5) {
      state = 0;
    }
    else {
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0 && state < 4) {
    state -= 1;
    delay(200);
    lcd.clear();
  }


  switch (state) {
    case 0:
      homeScreen();

      break;
    case 1:
      chooseLength();
      break;
    case 2:
      chooseQuantity();
      break;
    case 3:
      confirm();
      break;
    case 4:
      currentlyCutting();
      break;
    case 5:
      finishedCutting();
      break;
  }




  delay(100);

}

void homeScreen() {

  lcd.setCursor(0, 0);
  lcd.print("WELCOME");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
  digitalWrite(led3, HIGH);

}

void chooseLength() {
  Length = changeValue(Length);

  //clear LCD if required
  if (previousLength != Length) {
    lcd.clear();
    previousLength = Length;
  }

  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)Length + "inch");
  displayNavigation();
}

void chooseQuantity() {
  Quantity = changeValue(Quantity);

  //clear LCD if required
  if (previousQuantity != Quantity) {
    lcd.clear();
    previousQuantity = Quantity;
  }

  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("QUANTITY:" + (String)Quantity);
  displayNavigation();

}

void confirm() {
  lcd.setCursor(0, 0);
  lcd.print((String)Length + "inch x " + (String)Quantity + "pcs");
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);

}

void currentlyCutting() {

  digitalWrite(led3, LOW);

  lcd.setCursor(0, 0);
  lcd.print("PIC   = " + (String)0 + "/" + (String)Quantity);
  //lcd.setCursor(0, 1);



  for (int i = 0; i < Quantity; i++ ) {



    for (int x = 0; x < Length; ) {
      //int  val = digitalRead(Button);
      if ((Ultra()) == Length ) {
        digitalWrite(led, HIGH);
        digitalWrite(motor, LOW);
      } else {
        digitalWrite(led, LOW);
        digitalWrite(motor, HIGH);
      }
      if (digitalRead(led) == HIGH) {
        delay(200);
        x++;
      }



      lcd.setCursor(0, 1);
      lcd.print("LEG.  = " + (String)(Ultra()) + "/" + (String)Length  );


    }



    lcd.setCursor(0, 0);

    lcd.print("PIC   = " + (String)(i + 1) + "/" + (String)Quantity );


    snippers.write(closedAngle);
    delay(600);
    snippers.write(openAngle);
    delay(600);
    digitalWrite(led, LOW);
    delay(900);

    //lcd.setCursor(0, 1);

    //unsigned long timeRemaining = ((millis() - timeForOneCycle)*(Quantity - (i+1)))/1000;
    //lcd.print((String)timeRemaining + "s    ");

  }

  Length = 0;
  Quantity = 0;
  state = 5;
}

void finishedCutting() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CUTTING COMPLETE");
  //lcd.setCursor(11, 1);
  //lcd.print("NEXT>");
  timetoEnd();
  delay(100);

}

void timetoEnd() {
  for (int count = 10; count > 0; count --) {
    lcd.setCursor(6, 1);
    lcd.print((String(count)) + " s");
    digitalWrite(led2, HIGH);
    delay(1000);
    if (digitalRead(led) == HIGH)
      digitalWrite(led, LOW);
    digitalWrite(led2, LOW);
    state = 0;
  }
  lcd.clear();
}


int changeValue(int currentValue) {
  if (!digitalRead(upButton)) {
    delay(100);
    currentValue += incrementSpeed;

  }
  if (!digitalRead(downButton)) {
    if (currentValue - incrementSpeed >= 0) {
      delay(100);
      currentValue -= incrementSpeed;

    }
    else {
      currentValue = 0;
    }
  }
  if (!digitalRead(downButton) && !digitalRead(upButton)) {
    incrementSpeed = 1;
  }
  return currentValue;
}

void displayNavigation() {
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);

}

int Ultra() {

  long duration, inches;
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(pingPin, LOW);
  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);
  inches = microsecondsToInches(duration);
  //cm = microsecondsToCentimeters(duration);

}