//-----------------------------------------//
//
//-----------------------------------------//


//-----------------------------------------//

#include <Keypad.h>
#include <LiquidCrystal_I2C.h>


//-----------------------------------------//
//pinnout
//-----------------------------------------//
const int buzz = 10;
const int stop = 12;

LiquidCrystal_I2C   lcd(0x27, 16, 2);

//-----------------------------------------//
//settings
//-----------------------------------------//
const int ROW_NUM = 4; //four rows
const int COLUMN_NUM = 3; //three columns

char keys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte pin_rows[ROW_NUM] = {9, 8, 7, 6};   //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {5, 4, 3}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
//-----------------------------------------//
//minute setting
//-----------------------------------------//
String inputString;
long prepTime;
long defTime;
char key = keypad.getKey();
//-----------------------------------------//
//timer
//-----------------------------------------//
int Min = 0;
int sec = 0;
int mil;
unsigned int check_val = 50;
bool PREP = true;
bool RUN = true;
bool min_flag = true;

int prepare;
int minute;
//-----------------------------------------//
//random defuse number
//-----------------------------------------//
String inputNumber;
int pressCount = 1;
long inputInt;
long randNumber;
bool run = true;
//-----------------------------------------//



void setup() {
  //time settings
  Serial.begin(9600); // maximum number of digit for a number is 10, change if needed
  inputString.reserve(2); // maximum number of digit for a number is 10, change if needed

  // LCD Initialization
  lcd.backlight(); 
  lcd.init();
  lcd.clear();

  //random generator logic
  inputString.reserve(16); // maximum number of digit for a number is 10, change if needed
  randomSeed(analogRead(0));
  randNumber = random(1000, 9999);
  Serial.println(randNumber);

  //timer logic
  pinMode(buzz, OUTPUT); 
  digitalWrite(buzz, LOW);

  //run code
  prep();

  //passwordLogic();
}

void loop()
{
Serial.println("loop");
}

void prep()
{
  Serial.println("Enter Preparation Time");

  lcd.setCursor(0, 0);                                   //   Four is added to pressCount to center the input on the LCD
  lcd.print("Enter Prep Time");
  lcd.setCursor(0, 1);

  while (prepTime == 0)
  {
    char key = keypad.getKey();
    if (key) 
    {
    Serial.println(key);

    if (key >= '0' && key <= '9') 
    {     // only act on numeric keys
      inputString += key;
      lcd.print(key);              // append new character to input string
    } 
    else if (key == '#') 
    {
      if (inputString.length() > 0) {
        prepTime = inputString.toInt(); // YOU GOT AN INTEGER NUMBER
        inputString = "";               // clear input
        // DO YOUR WORK HERE
      Serial.print("Preparation Time Rntered: ");
      Serial.println(prepTime);
      deftime();
      }
    } 
    else if (key == '*') 
    {
      inputString = "";
      lcd.clear();
      lcd.setCursor(0, 0);                                   //   Four is added to pressCount to center the input on the LCD
      lcd.print("Enter Prep Time");
      lcd.setCursor(0, 1);                 // clear input
    }
    /*Serial.println(inputString);
    Serial.println(inputInt);*/
    }
  }
}

void deftime()
{
  Serial.println("Enter Defuse Time");

  lcd.clear();
  lcd.setCursor(0, 0);                                   //   Four is added to pressCount to center the input on the LCD
  lcd.print("Enter Def time");
  lcd.setCursor(0, 1);

  while (defTime == 0)
  {
    char key = keypad.getKey();
    if (key) 
    {
    Serial.println(key);

    if (key >= '0' && key <= '9') 
    {     // only act on numeric keys
      inputString += key;
      lcd.print(key);              // append new character to input string
    } 
    else if (key == '#') 
    {
      if (inputString.length() > 0) {
        defTime = inputString.toInt(); // YOU GOT AN INTEGER NUMBER
        inputString = "";               // clear input
        // DO YOUR WORK HERE
      Serial.print("Defuse Time: ");
      Serial.println(defTime);
      timerStart();
      }
    } 
    else if (key == '*') 
    {
      inputString = "";
      lcd.clear();
      lcd.setCursor(0, 0);                                   //   Four is added to pressCount to center the input on the LCD
      lcd.print("Enter Def Time:");
      lcd.setCursor(0, 1);                 // clear input
    }
    /*Serial.println(inputString);
    Serial.println(inputInt);*/
    }
  }
}


void timerStart()
{
  Serial.println("timer started");
  Serial.print("preparation time: ");
  Serial.println(prepTime);
  Serial.print("defuse time: ");
  Serial.println(defTime);

  lcd.clear();
  timersRun();
}


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------


void timersRun()
{
  

  prepare = prepTime;
  minute = defTime;
  Serial.println(prepare);
  Serial.println(minute);

  Min = prepare;

  
  delay(1500);
  INIT();
  delay(1000);
  prepTimer();
  lcd.clear();
}


int startTimer(unsigned long interval, void (*action)(int));

void prepTimer()
{
    lcd.clear();
    delay(250);
    PREP = true;
    while (PREP)
    {
      sec = sec - 1;
      delay(1000);
      if (sec == -1)
      {
        sec = 1;
        Min = Min - 1;
      }
      lcd.setCursor(2, 0);
      lcd.print("PREPARATION");
      lcd.setCursor(5, 1);
      //lcd.print(':');
      if (Min <= 9)
      {
        lcd.print('0');
      }
      lcd.print(Min);
      lcd.print(':');
      if (sec <= 9)
      {
        lcd.print('0');
      }
      lcd.print(sec);
      if (Min == 0 && sec == 0)
      {
        lcd.setCursor(4, 0);
        PREP = false;
        for (int i = 0; i < 20; i++)
        {
          digitalWrite(buzz, HIGH);
          delay(1000);
          digitalWrite(buzz, LOW);
          delay(1000);
          Min = minute;
          passwordLogic();
        }
      }
    }
}

/*void defuseTimer()
{
  Serial.println("def timer");
    lcd.clear();
    delay(250);
    RUN = true;
    while (RUN)
    {
      sec = sec - 1;
      //delay(1000);
      if (sec == -1)
      {
        sec = 59;
        Min = Min - 1;
      }
      lcd.setCursor(1, 0);
      lcd.print("DEFUSE");
      lcd.setCursor(9, 0);
      if (Min <= 9)
      {
        lcd.print('0');
      }
      lcd.print(Min);
      lcd.print(':');
      if (sec <= 9)
      {
        lcd.print('0');
      }
      lcd.print(sec);
      if (Min == 0 && sec == 0)
      {
        lcd.setCursor(4, 0);
        RUN = false;
        for (int i = 0; i < 20; i++)
        {
          /*digitalWrite(buzz, HIGH);
          delay(100);
          digitalWrite(buzz, LOW);
          delay(100);

        boom();
        }
      }
    }
}*/





void INIT()
{
  Min = Min;
  sec = 0;
  lcd.clear();
  lcd.setCursor(5, 0);
  lcd.print("READY?");
  lcd.setCursor(5, 1);
  if (Min <= 9)
  {
    lcd.print('0');
  }
  lcd.print(Min);
  lcd.print(':');
  if (sec <= 9)
  {
    lcd.print('0');
  }
  lcd.print(sec);
  min_flag = true;
  delay(500);
}


void boom()
{
  digitalWrite(buzz, HIGH); 
  delay(10000);
  digitalWrite(buzz, LOW);
  delay(250);
}

void win()
{
  delay(250);
  lcd.clear();
          lcd.setCursor(6, 0);
          lcd.print("WIN");
          lcd.setCursor(0, 1);
          lcd.print("****************");
  digitalWrite(buzz, HIGH); 
  delay(250);
  digitalWrite(buzz, LOW);
  delay(250);
  win();
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------





  
void passwordLogic()
{
  Serial.println("Enter Password");
  
  lcd.clear();
  lcd.setCursor(10, 1);
  lcd.print(randNumber);
  //lcd.setCursor(1, 1);

  static unsigned long nextSwitchTime = millis()+1;

  while (run = true)
  {
    Serial.println(pressCount);

  if( nextSwitchTime < millis() )
  {
    nextSwitchTime = millis() + 1L;

      mil = mil - 1;
      if (mil == -1)
      {
        mil = 999;
        sec = sec - 1;
      }
      if (sec == -1)
      {
        sec = 59;
        Min = Min - 1;
      }
      if (Min == -1) Min = 0;
      lcd.setCursor(0, 1);
      lcd.print("****************");
      lcd.setCursor(4, 0);
      if (Min <= 9)
      {
        lcd.print('0');
      }
      lcd.print(Min);
      lcd.print(':');
      if (sec <= 9)
      {
        lcd.print('0');
      }
      lcd.print(Min);
      lcd.print(':');
      if (mil <= 9)
      {
        lcd.print('0');
      }
      lcd.print(mil);
      if (Min == 0 && sec == 0 && mil == 0)
      {
        lcd.setCursor(4, 0);
        RUN = false;
        for (int i = 0; i < 20; i++)
        {
          boom
          ();
        }
      }

    if (pressCount == 1)
    {
      lcd.setCursor(2, 1);
    }
    else if (pressCount == 2)
    {
      lcd.setCursor(3, 1);
    }
    else if (pressCount == 3)
    {
      lcd.setCursor(4, 1);
    }
    else if (pressCount == 4)
    {
      lcd.setCursor(5, 1);
    }
  }

    char key = keypad.getKey();
    if (key) 
    {
    Serial.println(key);

    if (key >= '0' && key <= '9') 
    {     // only act on numeric keys
      inputNumber += key;
      pressCount++;
      lcd.print(key);              // append new character to input string
    }  

      if (inputNumber.length() == 4)
      {
      inputInt = inputNumber.toInt();
      if (inputInt == randNumber)
      {
         // YOU GOT AN INTEGER NUMBER
        inputNumber = "";               // clear input
        // DO YOUR WORK HERE
      Serial.print("defused");
      run = false;
      RUN = false;
      win();
      }
      else if (inputInt != randNumber)
      {        
      inputNumber = "";
      pressCount = 1;
      Serial.print("wrong");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("-----WRONG------");
      delay(3000);
      sec = sec - 3;
      lcd.clear();
      lcd.setCursor(10, 1);
      lcd.print(randNumber);
      lcd.setCursor(0, 1);
      }
      }
    Serial.println(inputString);
    Serial.println(inputInt);
    }
  }
}
4-Digit Display