#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);

const int button1 = 2;
bool buttonState1 = LOW;

const int button2 = 3;
bool buttonState2 = LOW;

const int button3 = 4;
bool buttonState3 = LOW;

const int button4 = 5;
bool buttonState4 = LOW;

const int correctPin = 8;
const int passwordPin = 6;
const int wrongPin = 7;

const int resetButton = 9;

bool resetButtonState = LOW;

const int newCodePin = 7;//10
const int passwordRecievePin = 6;//11
const int codeConfirmedPin = 8;//12

bool testState1 = LOW;
bool testState2 = LOW;
bool testState3 = HIGH;

int value1;
int value2;
int value3;
int value4;
int orderCheck = 1;

int pass1 = 1;
int pass2 = 2;
int pass3 = 3;
int pass4 = 4;

void setup() {
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(button4, INPUT);

  pinMode(correctPin, OUTPUT);
  pinMode(passwordPin, OUTPUT);
  pinMode(wrongPin, OUTPUT);

  pinMode(resetButton, INPUT);

  pinMode(newCodePin, OUTPUT);
  pinMode(passwordRecievePin, OUTPUT);
  pinMode(codeConfirmedPin, OUTPUT);

  Serial.begin(9600);

  lcd.begin();
  Wire.begin();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Enter the Code");
}
void loop() {
  if (debounceButton(resetButtonState, resetButton) == HIGH && resetButtonState == LOW)
  {
    resetButtonState = HIGH;
  }
  else if (debounceButton(resetButtonState, resetButton) == LOW && resetButtonState == HIGH)
  {
    resetButtonState = LOW;
    if (testState1 == LOW) {
      testState1 = HIGH;
      testState3 = LOW;
      digitalWrite(newCodePin, HIGH);
      lcd.clear();
      lcd.print("Enter Original");
      lcd.setCursor(0, 1);
      lcd.print("Code");

    } else if (testState1 == HIGH) {
      testState1 = LOW;
      testState3 = HIGH;
      digitalWrite(newCodePin, LOW);
    }
  }
  if (testState1 == HIGH) {
    if (debounceButton(buttonState1, button1) == HIGH || debounceButton(buttonState2, button2) == HIGH ||
        debounceButton(buttonState3, button3) == HIGH || debounceButton(buttonState4, button4) == HIGH) {

      switch (orderCheck) {
        case 1:     {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value1 = 1;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState2, button2) == HIGH) {
              value1 = 2;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value1 = 3;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState4, button4) == HIGH ) {
              value1 = 4;
              orderCheck = 2;
            }
            blink();
            delay(500);
            break;
          }
        case 2:     {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value2 = 1;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState2, button2) == HIGH ) {
              value2 = 2;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value2 = 3;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState4, button4) == HIGH) {
              value2 = 4;
              orderCheck = 3;
            }
            blink();
            delay(500);
            break;
          }
        case 3: {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value3 = 1;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState2, button2) == HIGH) {
              value3 = 2;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value3 = 3;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState4, button4) == HIGH) {
              value3 = 4;
              orderCheck = 4;
            }
            blink();
            delay(500);
            break;
          }
        case 4 : {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value4 = 1;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState2, button2) == HIGH ) {
              value4 = 2;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value4 = 3;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState4, button4) == HIGH ) {
              value4 = 4;
              orderCheck = 5;
            }
            blink();
            delay(500);

            if (value1 == pass1 && value2 == pass2 && value3 == pass3 && value4 == pass4 && orderCheck == 5) {
              testState1 = LOW;
              testState2 = HIGH;
              digitalWrite(newCodePin, LOW);
              digitalWrite(passwordRecievePin, HIGH);
              lcd.clear();
              lcd.print("Code accepted");
              delay(1000);
              lcd.clear();
              lcd.print("Enter new Code");
              value1 = 0;
              value2 = 0;
              value3 = 0;
              value4 = 0;
              orderCheck = 1;
            }
            else if (orderCheck == 5) {
              orderCheck = 1;
              testState1 = LOW;
              testState3 = HIGH;
              value1 = 0;
              value2 = 0;
              value3 = 0;
              value4 = 0;
              lcd.clear();
              lcd.print("Access Denied");
              delay(1000);
              for (int x = 0; x < 3; x++) {
                digitalWrite(newCodePin, HIGH);
                delay(300);
                digitalWrite(newCodePin, LOW);
                delay(300);
              }
              lcd.clear();
              lcd.print("Enter the Code");
              break;
            }
          }
      }
    }
  }
  if (testState2 == HIGH) {
    if (debounceButton(buttonState1, button1) == HIGH || debounceButton(buttonState2, button2) == HIGH ||
        debounceButton(buttonState3, button3) == HIGH || debounceButton(buttonState4, button4) == HIGH) {

      switch (orderCheck) {
        case 1:     {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value1 = 1;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState2, button2) == HIGH) {
              value1 = 2;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value1 = 3;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState4, button4) == HIGH ) {
              value1 = 4;
              orderCheck = 2;
            }
            blink();
            delay(500);
            break;
          }
        case 2:     {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value2 = 1;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState2, button2) == HIGH ) {
              value2 = 2;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value2 = 3;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState4, button4) == HIGH) {
              value2 = 4;
              orderCheck = 3;
            }
            blink();
            delay(500);
            break;
          }
        case 3: {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value3 = 1;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState2, button2) == HIGH) {
              value3 = 2;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value3 = 3;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState4, button4) == HIGH) {
              value3 = 4;
              orderCheck = 4;
            }
            blink();
            delay(500);
            break;
          }
        case 4 : {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value4 = 1;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState2, button2) == HIGH ) {
              value4 = 2;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value4 = 3;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState4, button4) == HIGH ) {
              value4 = 4;
              orderCheck = 5;
            }
            blink();
            delay(500);
            if (orderCheck == 5) {
              pass1 = value1;
              pass2 = value2;
              pass3 = value3;
              pass4 = value4;
              orderCheck = 1;
              digitalWrite(passwordRecievePin, LOW);
              lcd.clear();
              lcd.print("Code Reset");
              for (int x = 0; x < 3; x++) {
                digitalWrite(codeConfirmedPin, HIGH);
                delay(300);
                digitalWrite(codeConfirmedPin, LOW);
                delay(300);
                testState3 = HIGH;
                testState2 = LOW;
              }
              lcd.clear();
              lcd.print("Enter the Code");
            }
            break;
          }
      }
    }
  }
  if (testState3 == HIGH) {
    if (debounceButton(buttonState1, button1) == HIGH || debounceButton(buttonState2, button2) == HIGH ||
        debounceButton(buttonState3, button3) == HIGH || debounceButton(buttonState4, button4) == HIGH) {

      switch (orderCheck) {
        case 1:     {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value1 = 1;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState2, button2) == HIGH) {
              value1 = 2;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value1 = 3;
              orderCheck = 2;
            }

            else if (debounceButton(buttonState4, button4) == HIGH ) {
              value1 = 4;
              orderCheck = 2;
            }
            blink();
            delay(500);
            break;
          }
        case 2:     {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value2 = 1;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState2, button2) == HIGH ) {
              value2 = 2;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value2 = 3;
              orderCheck = 3;
            }

            else if (debounceButton(buttonState4, button4) == HIGH) {
              value2 = 4;
              orderCheck = 3;
            }
            blink();
            delay(500);
            break;
          }
        case 3: {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value3 = 1;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState2, button2) == HIGH) {
              value3 = 2;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value3 = 3;
              orderCheck = 4;
            }

            else if (debounceButton(buttonState4, button4) == HIGH) {
              value3 = 4;
              orderCheck = 4;
            }
            blink();
            delay(500);
            break;
          }
        case 4 : {

            if (debounceButton(buttonState1, button1) == HIGH ) {
              value4 = 1;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState2, button2) == HIGH ) {
              value4 = 2;
              orderCheck = 5;
            }

            else if (debounceButton(buttonState3, button3) == HIGH ) {
              value4 = 3;

              orderCheck = 5;
            }

            else if (debounceButton(buttonState4, button4) == HIGH ) {
              value4 = 4;
              orderCheck = 5;
            }
            blink();
            delay(500);
            if (value1 == pass1 && value2 == pass2 && value3 == pass3 && value4 == pass4 && orderCheck == 5) {
              value1 = 0;
              value2 = 0;
              value3 = 0;
              value4 = 0;
              orderCheck = 1;
              lcd.clear();
              lcd.print("Access Granted");
              digitalWrite(correctPin, HIGH);
              delay(3000);
              digitalWrite(correctPin, LOW);
              lcd.clear();
              lcd.print("Sample Done.");
              delay(1000);
              lcd.clear();
              lcd.print("Enter the code");
            }
            else if (orderCheck == 5) {
              orderCheck = 1;
              value1 = 0;
              value2 = 0;
              value3 = 0;
              value4 = 0;
              lcd.clear();
              lcd.print("Access Denied");
              digitalWrite(wrongPin, HIGH);
              delay(3000);
              digitalWrite(wrongPin, LOW);
              lcd.clear();
              lcd.print("Enter the Code");
            }
            break;
          }
      }
    }
  }
}

boolean debounceButton(boolean state, int buttonPin)
{
  boolean stateNow = digitalRead(buttonPin);
  if (state != stateNow)
  {
    delay(10);
    stateNow = digitalRead(buttonPin);
  }
  return stateNow;
}
void blink() {
  digitalWrite(passwordPin, HIGH);
  delay(50);
  digitalWrite(passwordPin, LOW);
  delay(50);
}
