#include<FastLED.h>

// timing things
unsigned long startTime;
unsigned long currentTime;
unsigned long second = 1015;
unsigned long hButtonTime;
unsigned long mButtonTime;
unsigned long debounceTime = 500;

// timekeeping things
int hrs = 0;
int mins = 0;
int secs = 0;

// button related declarations
#define HOUR_BUTTON     A2 // the pin that the hour button is connected to
#define MINUTE_BUTTON   A3 // the pin that the minute button is connected to
int lastHState = 1;
int lastMState = 1;

// led related things
#define NUM_LEDS      60 // how many leds in your strip? (60 is strongly recommended)
#define LED_DATA_PIN    2
CRGB leds[NUM_LEDS];
int ledHrs = 0;
int ledMins = 0;
int ledSecs = 0;
int totalMins = 0;

// distance modifiers
int skipDistance = NUM_LEDS / 60;
int hrSkipDistance = NUM_LEDS / 12;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200); // pour a bowl of serial
  pinMode(HOUR_BUTTON, INPUT_PULLUP); // this eliminates the need for an external pullup resistor
  pinMode(MINUTE_BUTTON, INPUT_PULLUP);
  FastLED.addLeds<WS2812B, LED_DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(255); // brightness value, between 0 and 255. Useful if the clock is too bright for you
  startTime = millis(); // what time did the program start, to keep track of timekeeping
}


void loop() {
  // put your main code here, to run repeatedly:
  //updating variables
  currentTime = millis();
  ledSecs = secs * skipDistance; // how many leds to skip in between seconds (if the 'face' has more than 60)
  ledMins = mins * skipDistance;
  ledHrs = (totalMins / 12) * skipDistance; // regardless of how big it is, the hour hand will always be at 1/12 the total minutes passed

  if (currentTime - startTime >= second) { // every second,
    secs++;                                // add a second
    Serial.print(hrs);
    Serial.print(":");
    Serial.print(mins);
    Serial.print(":");
    Serial.println(secs); // print the time to the serial connection, for debugging
    startTime = currentTime; // reset the second timer
  }


  // time setting
  if (digitalRead(HOUR_BUTTON) == 0 and digitalRead(HOUR_BUTTON) != lastHState) { // only react if the button wasn't pressed before
    hrs = hrs + 1;
    secs = 0;
    totalMins = totalMins + 60;
    lastHState = 0;
    hButtonTime = currentTime;
  }
  else if (currentTime - hButtonTime >= debounceTime) { // debounce for half a second, to ensure that the time doesn't increase by more than it should
    lastHState = 1;
  }

  if (digitalRead(MINUTE_BUTTON) == 0 and digitalRead(MINUTE_BUTTON) != lastMState) {
    mins = mins + 1;
    totalMins = totalMins + 1;
    secs = 0;
    lastMState = 0;
    mButtonTime = currentTime;
  }
  else if (currentTime - mButtonTime >= debounceTime) {
    lastMState = 1;
  }


  //time incrementing and overflow
  if (secs == 60) {
    secs = 0;
    mins = mins + 1;
    totalMins = totalMins + 1; // totalMins keeps track of the minutes passed, so the hour hand knows where to be
  }
  if (mins == 60) {
    mins = 0;
    hrs = hrs + 1;
  }
  if (hrs == 12) {
    hrs = 0;
  }
  if (totalMins == 720) { // there are 720 minutes in 12 hours, it will get reset after that time
    totalMins = 0;
  }

  // LED displaying
  FastLED.clear(); // wipe the slate before updating it
  leds[ledMins] = CRGB::Green; // what colors to set each 'hand' to?
  leds[ledSecs] = CRGB::DarkRed;
  leds[ledHrs] = CRGB::Blue;
  FastLED.show(); // having updated it, write the changes to the strip
}
