/*
   Project:       Daily Affirmation
   Description:   Stores strings in program memory and
                  displays one at random on button press.
                  See link below, this many chars won't
                  fit in an Uno's sram memory.
   Creation date: 12/15/23
   Author: AnonEngineering

   License: Beerware
   https://www.e-tinkers.com/2020/05/do-you-know-arduino-progmem-demystified/
*/

#include <LiquidCrystal_I2C.h>
#include "affirmations.h"

const unsigned long shutoffDelay = 10000; // 30 seconds shutoff delay
const int NUM_STRINGS = 51;
const int STRING_SIZE = 60; // max chars for 3 lines
const int BTN_PIN = 2;
const int I2C_ADDR = 0x27;
const int NUM_COLS = 20;
const int NUM_ROWS = 4;

PGM_P const affirmations[NUM_STRINGS] PROGMEM =
{
  afStr0,   afStr1,  afStr2,  afStr3,  afStr4,  afStr5,  afStr6,  afStr7,  afStr8,  afStr9,
  afStr10, afStr11, afStr12, afStr13, afStr14, afStr15, afStr16, afStr17, afStr18, afStr19,
  afStr20, afStr21, afStr22, afStr23, afStr24, afStr25, afStr26, afStr27, afStr28, afStr29,
  afStr30, afStr31, afStr32, afStr33, afStr34, afStr35, afStr36, afStr37, afStr38, afStr39,
  afStr40, afStr41, afStr42, afStr43, afStr44, afStr45, afStr46, afStr47, afStr48, afStr49,
  afStr50
};

bool isRunning = false;
unsigned long shutOffTimer = 0;

LiquidCrystal_I2C lcd(I2C_ADDR, NUM_COLS, NUM_ROWS);

bool checkButton() {
  static int oldBtnState = HIGH;
  bool isButtonPressed = false;

  int btnState = digitalRead(BTN_PIN);
  if (btnState != oldBtnState) {
    oldBtnState = btnState;
    if (btnState == LOW) {
      isButtonPressed = true;
      // if not running show splash
      if (!isRunning) {
        showSplash();
        delay(1000);
      }
      Serial.println("Get new affirmation");
      isRunning = true;
      // Reset the shutoff timer when the button is pressed
      shutOffTimer = millis();
    } else {
      Serial.println("Button released\n");
      isRunning = true;
    }
    delay(20);  // for debounce
  }
  return isButtonPressed;
}

void displayRandomAffirmation() {
  char buffer[60];

  lcd.clear();
  int lineNumber = 1;
  int index = random(NUM_STRINGS);
  Serial.print("Random index: ");
  Serial.println(index);
  // Get random string from affirmations
  strcpy_P(buffer, (PGM_P)pgm_read_word(&affirmations[index]));
  //Serial.print("Buffer length: ");
  //const int buf_len = strlen_P(affirmations[index]);
  //Serial.println(buf_len);
  Serial.println(buffer);
  char * pch;
  pch = strtok (buffer, ";-");
  while (pch != NULL) {
    lcd.setCursor(0, lineNumber);
    lcd.print(pch);
    Serial.println (pch);
    lineNumber++;
    if (lineNumber > 3) lineNumber = 1;
    pch = strtok (NULL, ";-");
  }
}

void showSplash() {
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(2, 1);
  lcd.print("Here is your");
  lcd.setCursor(6, 2);
  lcd.print("affirmation!");
  isRunning = true;
}

void shutOffDisplay() {
  if (isRunning && (millis() - shutOffTimer >= shutoffDelay)) {
    lcd.clear();
    lcd.noBacklight();
    isRunning = false;
    Serial.println("Display and backlight shutoff");
  }
}

void setup() {
  Serial.begin(115200);
  lcd.begin(20, 4);
  pinMode(BTN_PIN, INPUT_PULLUP);
  randomSeed(analogRead(0));
  showSplash();
}

void loop() {
  if (checkButton()) {
    displayRandomAffirmation();
  }
  shutOffDisplay();
}