// Arduino Security System
// Made by: Vasco2020
// I2C Version is discontinued due to hardware avalilability
String PASSCODE = "1234"; //What PIN Should be used to disarm the alarm
int COUNTDOWN_TIME = 10; //How much time will it take for the countdown
bool IR_ENABLE = true; //Should IR remote control start enabled? [YES:1][NO:0]
#include <Keypad.h>
#include <IRremote.h>
#include <LiquidCrystal.h>
//Pin Assignment
int BUZZER = 13; //Change Buzzer Pin
int GREEN_LED = 12; //Change Green LED (Dissarmed indicator) Pin
int RED_LED = 11; //Change Red LED (Armed Indicator) Pin
int RECV_PIN = 0; //Change IR Receiver (IR Remote Control Receiver) Pin
int MOTION_SENSOR = 10; //Change Trigger (PIR Motion) Pin
//IR Remote Sensor stuff
int IR_REMOTE = RECV_PIN;
decode_results results;//  A variable that would be used by receiver to put the key code into
bool manual_buzzer = false;
bool TRIGGER_STATE = false;
//LCD Stuff
LiquidCrystal lcd(9 , 8 , 7 , 6 , 5 , 4);
//Keypad Stuff
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', '#', 'D' }
};
uint8_t rowPins[COLS] = { 3, 2, A5, A4 }; // Pins connected to R1, R2, R3, R4
uint8_t colPins[ROWS] = { A0, A1, A2, A3 }; // Pins connected to C1, C2, C3, C4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//Functions
void arming() {
  digitalWrite(BUZZER, HIGH);
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("Arming Alarm... ");
  lcd.setCursor(0, 1);
  delay(500);
  digitalWrite(BUZZER, LOW);
  delay(1000);
  for (int i = COUNTDOWN_TIME; i >= 0; i--) {
    lcd.setCursor(0, 1);
    lcd.print("Time: ");
    lcd.print(i);
    lcd.print("s     ");
    digitalWrite(BUZZER, HIGH);
    delay(100);
    digitalWrite(BUZZER, LOW);
    delay(900);
  };
  digitalWrite(BUZZER, HIGH);
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("Countdown       ");
  lcd.setCursor(0, 1);
  lcd.print("Complete.       ");
  delay(500);
  digitalWrite(BUZZER, LOW);
  delay(500);
  digitalWrite(BUZZER, LOW);
  digitalWrite(RED_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("Alarm Armed.    ");
  delay(250);
};
void beta_testing() {
  lcd.setCursor(0, 0);
  lcd.print("Entering Beta   ");
  lcd.setCursor(0, 1);
  lcd.print("Testing Mode... ");
  for (int i = 3; i >= 0;i--){
    digitalWrite(BUZZER, HIGH);
    delay(500);
    digitalWrite(BUZZER, LOW);
    delay(250);
  };
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("BETA TESTING: ON ");
  digitalWrite(RED_LED, HIGH);
  digitalWrite(GREEN_LED, LOW);
};
void disarm() {
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("Alarm Disarmed. ");
  digitalWrite(BUZZER, LOW);
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, HIGH);
  manual_buzzer = false;
  TRIGGER_STATE = false;
  delay(1000);
};
void startup_sequence() {
  // Startup Conection Indicator LEDs
  digitalWrite(BUZZER, LOW);
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  delay(750);
  lcd.setCursor(0, 0);
  lcd.print("Arduino Security");
  lcd.setCursor(0, 1);
  lcd.print("System BETA v0.2");
  digitalWrite(BUZZER, HIGH);
  digitalWrite(RED_LED, HIGH);
  digitalWrite(GREEN_LED, HIGH);
  delay(1000);
  digitalWrite(BUZZER, LOW);
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  delay(500);
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("Booting up  ... ");
  lcd.setCursor(0, 1);
  lcd.print("Please Wait ... ");
  delay(250);
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);
  delay(500);
  digitalWrite(GREEN_LED, HIGH);
  delay(100);
  digitalWrite(GREEN_LED, LOW);
  delay(500);
  digitalWrite(RED_LED, HIGH);
  delay(100);
  digitalWrite(RED_LED, LOW);
  delay(250);
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("...             ");
  digitalWrite(BUZZER, HIGH);
  digitalWrite(RED_LED, HIGH);
  digitalWrite(GREEN_LED, HIGH);
  delay(250);
  digitalWrite(BUZZER, LOW);
  digitalWrite(RED_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  delay(250);
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("Boot up Complete");
  delay(750);
  digitalWrite(GREEN_LED, HIGH);
  lcd.setCursor(0, 0);
  lcd.clear();
  lcd.print("-----Online-----");
  for (int i= 3; i>= 0; i--) {
    digitalWrite(BUZZER, HIGH);
    delay(75);
    digitalWrite(BUZZER, LOW);
    delay(75);
  };
  delay(250);
};
void setup() {
  Serial.begin(115200);
  pinMode(BUZZER, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(RED_LED, OUTPUT);
  pinMode(IR_REMOTE, INPUT);
  pinMode(MOTION_SENSOR, INPUT);
  IrReceiver.enableIRIn(); // Start the receiver
  lcd.begin(16, 2); //Start and Set display Resolution
  startup_sequence();
}
void loop() {
  if (digitalRead(GREEN_LED) && digitalRead(RED_LED)) { //Safe Guard
    lcd.setCursor(0, 0);
    lcd.clear();
    lcd.print("-----ERROR!-----");
    delay(1000);
    lcd.setCursor(0, 1);
    lcd.print("Rebooting ...   ");
    delay(2500);
    startup_sequence();
  };
  if (digitalRead(GREEN_LED)) {
    lcd.setCursor(0, 0);
    lcd.print("Online---");
    if (IR_ENABLE) {
      lcd.print("-IR: ON");
    };
    if (!IR_ENABLE) {
      lcd.print("IR: OFF");
    };
    lcd.setCursor(0, 1);
    if (!manual_buzzer) {
    lcd.print("Buzzer: OFF     ");
    };
    if (manual_buzzer) {
      lcd.print("Buzzer: ON      ");
    };
  };
  if (digitalRead(MOTION_SENSOR) && digitalRead(RED_LED) && TRIGGER_STATE == 0) {
    Serial.println("ALARM TRIGGERED!");
    lcd.setCursor(0, 0);
    lcd.print("ALARM TRIGGERED!");
    Serial.println("");
    TRIGGER_STATE = true;
    manual_buzzer = true;
    digitalWrite(BUZZER, HIGH);
  };
  if (IrReceiver.decode() > 0 && IR_ENABLE == 1) {
    Serial.println(IrReceiver.decodedIRData.decodedRawData);
    int remoteinput = IrReceiver.decodedIRData.decodedRawData;
    if (digitalRead(GREEN_LED) && remoteinput == 1570963200) {
      Serial.println("Arming Alarm from Remote...");
      arming();
      Serial.println("Alarm Armed from Remote.");
      Serial.println("");
      IrReceiver.resume();
      return;
    }
    if (digitalRead(GREEN_LED) && remoteinput == 3710058240) {
      Serial.println("Entering Beta Testing Mode from Remote...");
      beta_testing();
      Serial.println("Beta Testing Mode Activated from Remote.");
      Serial.println("");
      IrReceiver.resume();
      return;
    }
    if (digitalRead(RED_LED) && remoteinput == 1570963200)  {
      disarm();
      Serial.println("Alarm Disarmed from Remote.");
      Serial.println("");
      IrReceiver.resume();
      return;
    }
    if (manual_buzzer == 0 && remoteinput == 1470693120) {
      digitalWrite(BUZZER, HIGH);
      TRIGGER_STATE = 1;
      manual_buzzer = 1;
      Serial.println("Remote Manual Buzzer Activated.");
      lcd.setCursor(0, 1);
      lcd.print("Buzzer: ON      ");
      Serial.println("");
      IrReceiver.resume();
      return;
    }
    if (manual_buzzer == 1 && remoteinput == 1470693120) {
      digitalWrite(BUZZER, LOW);
      Serial.println("Remote Manual Buzzer Deactivated.");
      lcd.setCursor(0, 1);
      lcd.print("Buzzer: OFF     ");
      Serial.println("");
      TRIGGER_STATE = 0;
      manual_buzzer = 0;
      IrReceiver.resume();
      return;
    }
  }
  char key = keypad.getKey();
  while (true) {Serial.println(key);}
  if (key == '#') { //If # is pressed and Buzzer is active
    delay(100);
    for (TRIGGER_STATE == 1; digitalRead(BUZZER);) {
      String keypadcode = ""; // Initialize an empty string
      lcd.setCursor(0, 0);
      lcd.clear();
      lcd.print("Code------Disarm");
      lcd.setCursor(0, 1);
      lcd.print("PIN: ____       ");
      keypadcode += keypad.waitForKey();
      lcd.setCursor(0, 1);
      lcd.print("PIN: #___       ");
      delay(50);
      keypadcode += keypad.waitForKey();
      lcd.setCursor(0, 1);
      lcd.print("PIN: ##__       ");
      delay(50);
      keypadcode += keypad.waitForKey();
      lcd.setCursor(0, 1);
      lcd.print("PIN: ###_       ");
      delay(50);
      keypadcode += keypad.waitForKey();
      lcd.setCursor(0, 1);
      lcd.print("PIN: ####       ");
      Serial.println(keypadcode);
      delay(250);
      if (keypadcode == PASSCODE) {
        disarm();
        Serial.println("CODE INFO: CORRECT CODE");
        Serial.println("Alarm Disarmed from Keypad.");
        Serial.println("");
        delay(750);
      }
      else {
        lcd.setCursor(0, 1);
        lcd.print("PIN: #### ERROR ");
        Serial.println("ERROR: WRONGCODE");
        delay(500);
      }
    }
  }
  if (key == '*' && digitalRead(GREEN_LED)) { //If # is pressed and Buzzer is active
    delay(100);
    String keypadcode = ""; // Initialize an empty string
    lcd.setCursor(0, 0);
    lcd.clear();
    lcd.print("Code---IR_Toggle");
    lcd.setCursor(0, 1);
    lcd.print("PIN: ____       ");
    keypadcode += keypad.waitForKey();
    lcd.setCursor(0, 1);
    lcd.print("PIN: #___       ");
    delay(50);
    keypadcode += keypad.waitForKey();
    lcd.setCursor(0, 1);
    lcd.print("PIN: ##__       ");
    delay(50);
    keypadcode += keypad.waitForKey();
    lcd.setCursor(0, 1);
    lcd.print("PIN: ###_       ");
    delay(50);
    keypadcode += keypad.waitForKey();
    lcd.setCursor(0, 1);
    lcd.print("PIN: ####       ");
    Serial.println(keypadcode);
    delay(250);
    if (keypadcode == PASSCODE) {
      Serial.println("CODE INFO: CORRECT CODE");
      if (keypadcode == PASSCODE && IR_ENABLE == 1) {
        lcd.setCursor(0, 0);
        lcd.clear();
        lcd.print("IR Control OFF. ");
        Serial.println("IR Control Deactivated from Keypad.");
        Serial.println("");
        IR_ENABLE = 0;
        keypadcode = "0";
        IrReceiver.resume();
        delay(750);
      }
      if (keypadcode == PASSCODE && IR_ENABLE == 0) {
        lcd.setCursor(0, 0);
        lcd.clear();
        lcd.print("IR Control ON.  ");
        Serial.println("IR Control Activated from Keypad.");
        Serial.println("");
        IR_ENABLE = 1;
        keypadcode = "0";
        IrReceiver.resume();
        delay(750);
      }
    }
    else {
      lcd.setCursor(0, 1);
      lcd.print("PIN: #### ERROR ");
      Serial.println("ERROR: WRONGCODE");
      delay(500);
    }
  }
  if (key == 'A' && digitalRead(GREEN_LED)) { //Arm the Alarm
    Serial.println("Arming Alarm from Keypad...");
    arming();
    Serial.println("Alarm Armed from Keypad.");
    Serial.println("");
  }
  if (key == 'B' && digitalRead(GREEN_LED)) { //BETA MODE: Testing the Alarm Without having to wait for too long
    Serial.println("Entering Beta Testing Mode from Keypad...");
    beta_testing();
    Serial.println("Beta Testing Mode Activated from Keypad.");
    Serial.println("");
  }
}