/*
 * Clock_LED_Button_TimeChange by beta1042
 * https://www.youtube.com/watch?v=IIiMjMNGg8g&lc=UgwuhdciO80rqHdsMIx4AaABAg.A8YblHYAzL7A8eyfMKtjYQ
*/

#include <IRremote.hpp>
const int RECV_PIN = 6;
IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long IR_Value = 0;
/*
9768FF00   Key 0
CF30FF00   Key 1
E718FF00   Key 2
857AFF00   Key 3
EF10FF00   Key 4
C738FF00   Key 5
A55AFF00   Key 6 
BD42FF00   Key 7
B54AFF00   Key 8
AD52FF00   Key 9

without FastLED.show();
9768FF00  Key 0
9768FF00
9768FF00

with FastLED.show();
541D6170  Key 0
D1ADAC46
A85442CF

*/
#include <Wire.h>
#include <RTClib.h>
#include <FastLED.h>

#define LED_PIN  7
#define NUM_LEDS 60
#define BRIGHTNESS  32
#define LED_TYPE  WS2812
#define COLOR_ORDER GRB

// https://howtomechatronics.com/tutorials/arduino/how-to-control-ws2812b-individually-addressable-leds-using-arduino/
// https://create.arduino.cc/projecthub/antiElectron/simple-wall-clock-using-adafruit-1-4-60-ring-neopixel-8ca99c?ref=tag&ref_id=clocks&offset=81

// RTC com CR2032 - Corte a TRILHA ou Remova o DIODO!!!!!!!!
// https://www.onetransistor.eu/2019/07/zs042-ds3231-battery-charging-circuit.html

CRGB leds[NUM_LEDS];

RTC_DS3231 RTC; // Define o módulo RTC
DateTime Clock; // Mantém a hora atual do relógio

byte hourval, minuteval, secondval;
int adjusthr, adjustmin, adjustsec;

//************Botões*****************//
int P1 = 3; // Botão de Horas (D3)
int P2 = 4; // Botão de Minutos (D4)
int P3 = 5; // Botão de Segundos (D5)

// As variáveis ​​mudarão:
int lastButtonStateP1 = LOW; // a leitura anterior do pino de entrada
int lastButtonStateP2 = LOW;
int lastButtonStateP3 = LOW;

void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  Wire.begin(); // Inicia o I2C
  RTC.begin();  // Inicia o RTC

  pinMode(P1, INPUT_PULLUP);
  pinMode(P2, INPUT_PULLUP);
  pinMode(P3, INPUT_PULLUP);

  if (! RTC.lostPower()) {
    // Serial.println("RTC is NOT running!");
    // A linha a seguir define o RTC para a data e hora em que este sketch foi compilado
    // RTC.adjust(DateTime(__DATE__, __TIME__));
  }

  FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.clear(); // limpa todos os dados de pixel
  FastLED.setBrightness(  BRIGHTNESS );
  FastLED.show();
}

void flash2hour(int flashhr) { // 'flashhr' deve ser a posição do LED. Ex. 6 horas são 30 flashhr (ou metade dos LEDs no relógio)
  int adji;

  for (int i = 1; i <= flashhr; i++) {
    if (i >= 30) {
      adji = i - 30;
    }
    else {
      adji = i + 30;
    }
    leds[adji] = CRGB(255, 0, 0); // Vermelho
    FastLED.show();

    leds[adji] = CRGB(0, 0, 0); // Preto (apagado)
    delay(100);
  }
}

void loop() {

   if (IrReceiver.decode()) {
    IR_Value = IrReceiver.decodedIRData.decodedRawData;
    Serial.println(IR_Value, HEX);
    delay(1000);
    irrecv.resume();
  }

  Clock = RTC.now(); // obtém o tempo do RTC

  secondval = Clock.second(); // obtém segundos
  minuteval = Clock.minute(); // obtém minutos
  hourval = Clock.hour();     // obtém horas

  // Esta linha define o RTC com uma data e hora explícitas. Por exemplo, para definir...
  // January 21, 2014 às 3:02am, você chamaria:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 2));

  // Lê o estado do botão em uma variável local:
  int readingP1 = digitalRead(P1);
  int readingP2 = digitalRead(P2);
  int readingP3 = digitalRead(P3);

  // Verifica se você pressionou o botão
  // (i.e. a entrada foi de LOW para HIGH), e você esperou tempo
  // suficiente desde a última pressão para ignorar qualquer ruído.

  // Verifica se você pressionou o botão de Horas, e incrementa em 1
  if (readingP1 != lastButtonStateP1)
  {
    if (readingP1 == HIGH) {
      if (hourval == 23) {
        hourval = 0; // apenas 24 horas, inicia em 0, então faz reset para 0
      }
      else {
        hourval += 1; // avança em 1
      }
      RTC.adjust(DateTime(Clock.year(), Clock.month(), Clock.day(), hourval, Clock.minute(), Clock.second()));
    }
  }

  // Verifica se você pressionou o botão Minuto, e incrementa em 1
  if (readingP2 != lastButtonStateP2)
  {
    if (readingP2 == HIGH) {
      if (minuteval == 59) {
        minuteval = 0;
      }
      else {
        minuteval += 1; // avança por 1
      }
      RTC.adjust(DateTime(Clock.year(), Clock.month(), Clock.day(), Clock.hour(), minuteval, Clock.second()));
    }
  }

  // Verifica se você pressionou o botão de Segundos, e faz o reset para 0
  if (readingP3 != lastButtonStateP3)
  {
    if (readingP3 == HIGH) {
      secondval = 0;
      RTC.adjust(DateTime(Clock.year(), Clock.month(), Clock.day(), Clock.hour(), Clock.minute(), secondval));
    }
  }

  if (hourval > 11) hourval -= 12; // Este relógio é de 12 horas; se for de 13-23, converta para 0-11
  //  hourval = (hourval*60 + minuteval) / 12;
  hourval = (hourval * 60) / 12;

  // Ajusta os valores, pois a tira de LED inicia na marca de 6 horas em vez de 12 (ligado próximo a 6)
  if (hourval >= 30) {
    adjusthr = hourval - 30;
  }
  else {
    adjusthr = hourval + 30;
  }

  if (minuteval >= 30) {
    adjustmin = minuteval - 30;
  }
  else {
    adjustmin = minuteval + 30;
  }

  if (secondval >= 30) {
    adjustsec = secondval - 30;
  }
  else {
    adjustsec = secondval + 30;
  }

  if (minuteval == 0 && secondval == 0) {
    flash2hour(hourval);
  }

  leds[adjusthr] = CRGB(255, 0, 0); // Vermelho
  // leds[hourval-1] = CRGB(0, 0, 0); // Cor mais clara que o vermelho
  // leds[hourval+1] = CRGB(0, 0, 0);

  leds[adjustmin] = CRGB(0, 0, 255); // Azul
  // strip.setPixelColor(minuteval-1, 0x200020);strip.setPixelColor(minuteval+1, 0x200020);

  leds[adjustsec] = CRGB(0, 255, 0); // Verde

  FastLED.show();

  leds[adjusthr] = CRGB(0, 0, 0); // Preto
  leds[adjustmin] = CRGB(0, 0, 0); // Preto
  leds[adjustsec] = CRGB(0, 0, 0); // Preto

  delay(25);
  lastButtonStateP1 = readingP1;
  lastButtonStateP2 = readingP2;
  lastButtonStateP3 = readingP3;

  /*
     Serial.print(hourval, DEC);
     Serial.print(':');
     Serial.print(minuteval, DEC);
     Serial.print(':');
     Serial.println(secondval, DEC);
  */
}
GND5VSDASCLSQWRTCDS1307+