/// DISPLAY 4x7-segmento 5461AS-1 (45) VERIFICAR SE COMMON ANODE ou CATHODE
/// ON@ -> Cathode = HIGH; Anode = LOW (SINK com resistor ao PCF)

/// READ ME:
/// Pressiona MENU para definir um horario para o ALARME
/// Ao inserir digito válido, pressiona PLAY para avançar ao próximo campo
/// Concluido os 4 digitos, pressiona PLAY p/ salvar HORA DO ALARME
/// Pressiona POWER p/ Liga/desliga alarme.

/// RTC DS1302, LCD 16x2, Adaptador LCD I2C PCF8574, IR Receptor 1838, Buzzer

#include <IRremote.hpp>       // Do not change header order.
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>

#define IR_PIN 8
#define BUZZER_PIN 13

RTC_DS1307 rtc; // &I2C =? 0x68 /// No slide diz 1302/1307. Se 1302 precisa mudar Lib
LiquidCrystal_I2C lcd(0x27,20,4);

bool blink = true, alarmArmed = false;
int irCode = 0;
int timeNow[5];
int alarmSettings[4];

void setup() {
  Serial.begin(9600);
  pinMode(BUZZER_PIN, OUTPUT);
  if (!rtc.begin()) {
    Serial.println("Nao foi possivel conectar ao RTC DS1307");
    while (1);
  }
  lcd.init();
  lcd.backlight();
  IrReceiver.begin(IR_PIN);
  EEPROM.get(0, alarmSettings);
}

void loop() {
  printTime();
  if (alarmArmed) checkAlarm();
  irCode = irReceive();
  if (irCode == 0xE2) setAlarmTime();
  if (irCode == 0xA2) {
    alarmArmed = !alarmArmed;
    lcd.clear();
  }
}

void getTime() {
  DateTime n = rtc.now();
  timeNow[0] = n.hour() / 10;
  timeNow[1] = n.hour() % 10;
  timeNow[2] = n.minute() / 10;
  timeNow[3] = n.minute() % 10;
  timeNow[4] = n.second();
}

void printTime() {
  getTime();
  lcd.setCursor(4, 0);
  for (int i = 0; i < 4; i++) {
    lcd.print(timeNow[i]);
    if (i == 1 || i == 3) lcd.print(":");
  }
  if (timeNow[4] < 10) lcd.print("0");
  lcd.print(timeNow[4]);
  if (alarmArmed) {
    lcd.setCursor(14, 0);
    lcd.print("ON");
  }
  delay(200);
}

int irReceive() {
  int received = 0;
  if (IrReceiver.decode()) {
    if (IrReceiver.decodedIRData.protocol == NEC) {
      received = IrReceiver.decodedIRData.command;
    }
    IrReceiver.resume();
  }
  return received;
}

int getButtonFromHex(int hex) {
  int hexCode[10] = {0x68, 0x30, 0x18, 0x7A, 0x10,
                     0x38, 0x5A, 0x42, 0x4A, 0x52}; // 0 à 9
  if (hex == 0xA2) return 10; // POWER
  if (hex == 0xE2) return 11; // MENU
  if (hex == 0xA8) return 12; // PLAY
  for (int i = 0; i < 10; i++) {
    if (hexCode[i] == hex) return i;
  }
  return -1;
}

void setAlarmTime() {
  bool rollback = false;
  int alarm[4] = {0};
  for (int i = 0; i < 4; i++) alarm[i] = alarmSettings[i];
  int count = 0;

  while (!rollback){
    printTime();
    printSetAlarm(alarm, count);
    if (count > 3) break;
    irCode = getButtonFromHex(irReceive());

    if (irCode == 11) rollback = true;
    else if (irCode == 12) count++;

    else if (irCode >= 0 && irCode < 10) {
      if (count == 0) {
        if (irCode == 0 || irCode == 1) alarm[0] = irCode;
        else {
          alarm[0] = 2;
          alarm[1] = (alarm[1] < 4) ? alarm[1] : 3;
        }
      } else if (count == 1) {
        if (alarm[0] < 2) alarm[1] = irCode;
        else alarm[1] = (irCode < 4) ? irCode : 3;
      } else if (count == 2) alarm[2] = (irCode < 6) ? irCode : 5;
      else alarm[3] = irCode;
    }
    else continue;
  }
  if (!rollback) {
    for (int i = 0; i < 4; i++) {
      alarmSettings[i] = alarm[i];
    }
    EEPROM.put(0, alarmSettings);
  }
  lcd.clear();
}

void printSetAlarm(int *a, int digit) {
  blink = !blink;
  lcd.setCursor(2, 1);
  lcd.print("ALARME ");
  for (int i = 0; i < 4; i++) {
    if (i == 2) lcd.print(":");
    if (digit == i && blink) lcd.print(" ");
    else lcd.print(a[i]);
  }
}

void checkAlarm() {
  bool bip = true;
  for (int i = 0; i < 4; i++) {
    bip = (alarmSettings[i] != timeNow[i]) ? false : bip;
  }
  while (bip) {
    digitalWrite(BUZZER_PIN, !blink);
    blink = !blink;
    printTime();
    lcd.setCursor(5, 1);
    lcd.print((blink) ? "       " : "BIP!!!");
    if (irReceive() == 0xA2) {
      alarmArmed = false;
      bip = false;
      lcd.clear();
    }
  }
  digitalWrite(BUZZER_PIN, LOW);
}
GND5VSDASCLSQWRTCDS1307+