
/*
 * This file allows you to add own functionality to WLED more easily
 * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
 * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
 * bytes 2400+ are currently ununsed, but might be used for future wled features
 */

/*
 * Pin 2 of the TTGO T-Display serves as the data line for the LED string.
 * Pin 35 is set up as the button pin in the platformio_overrides.ini file.
 * The button can be set up via the macros section in the web interface.
 * I use the button to cycle between presets.
 * The Pin 35 button is the one on the RIGHT side of the USB-C port on the board,
 * when the port is oriented downwards.  See readme.md file for photo.
 * The display is set up to turn off after 5 minutes, and turns on automatically 
 * when a change in the dipslayed info is detected (within a 5 second interval).
 */
 

//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)

#include "wled.h"
#include <TFT_eSPI.h>
#include <SPI.h>
#include "WiFi.h"
#include <Wire.h>

#ifndef TFT_DISPOFF
#define TFT_DISPOFF 0x28
#endif

#ifndef TFT_SLPIN
#define TFT_SLPIN   0x10
#endif

#define TFT_MOSI            19
#define TFT_SCLK            18
#define TFT_CS              5
#define TFT_DC              16
#define TFT_RST             23

#define TFT_BL          4  // Display backlight control pin
#define ADC_EN          14  // Used for enabling battery voltage measurements - not used in this program

TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library

//gets called once at boot. Do all initialization that doesn't depend on network here
void userSetup() {
    Serial.begin(115200);
    Serial.println("Start");
    tft.init();
    tft.setRotation(3);  //Rotation here is set up for the text to be readable with the port on the left. Use 1 to flip.
    tft.fillScreen(TFT_BLACK);
    tft.setTextSize(2);
    tft.setTextColor(TFT_WHITE);
    tft.setCursor(1, 10);
    tft.setTextDatum(MC_DATUM);
    tft.setTextSize(3);
    tft.print("Loading...");

    if (TFT_BL > 0) { // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
         pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
         digitalWrite(TFT_BL, HIGH); // Turn backlight on. 
    }

    // tft.setRotation(3);
}

// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
void userConnected() {}

// needRedraw marks if redraw is required to prevent often redrawing.
bool needRedraw = true;

// Next variables hold the previous known values to determine if redraw is
// required.
String knownSsid = "";
IPAddress knownIp;
uint8_t knownBrightness = 0;
uint8_t knownMode = 0;
uint8_t knownPalette = 0;
uint8_t tftcharwidth = 19;  // Number of chars that fit on screen with text size set to 2

long lastUpdate = 0;
long lastRedraw = 0;
bool displayTurnedOff = false;
// How often we are redrawing screen
#define USER_LOOP_REFRESH_RATE_MS 5000

void userLoop() {

  // Check if we time interval for redrawing passes.
  if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
    return;
  }
  lastUpdate = millis();
  
  // Turn off display after 5 minutes with no change.
   if(!displayTurnedOff && millis() - lastRedraw > 5*60*1000) {
    digitalWrite(TFT_BL, LOW); // Turn backlight off. 
    displayTurnedOff = true;
  } 

  // Check if values which are shown on display changed from the last time.
  if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
    needRedraw = true;
  } else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
    needRedraw = true;
  } else if (knownBrightness != bri) {
    needRedraw = true;
  } else if (knownMode != strip.getMode()) {
    needRedraw = true;
  } else if (knownPalette != strip.getSegment(0).palette) {
    needRedraw = true;
  }

  if (!needRedraw) {
    return;
  }
  needRedraw = false;
  
  if (displayTurnedOff)
  {
    digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on.
    displayTurnedOff = false;
  }
  lastRedraw = millis();

  // Update last known values.
  #if defined(ESP8266)
  knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
  #else
  knownSsid = WiFi.SSID();
  #endif
  knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
  knownBrightness = bri;
  knownMode = strip.getMode();
  knownPalette = strip.getSegment(0).palette;

  tft.fillScreen(TFT_BLACK);
  tft.setTextSize(2);
  // First row with Wifi name
  tft.setCursor(1, 1);
  tft.print(knownSsid.substring(0, tftcharwidth > 1 ? tftcharwidth - 1 : 0));
  // Print `~` char to indicate that SSID is longer, than our dicplay
  if (knownSsid.length() > tftcharwidth)
    tft.print("~");

  // Second row with AP IP and Password or IP
  tft.setTextSize(2);
  tft.setCursor(1, 24);
  // Print AP IP and password in AP mode or knownIP if AP not active.
  // if (apActive && bri == 0)
  //   tft.print(apPass);
  // else
  //   tft.print(knownIp);

  if (apActive) {
    tft.print("AP IP: ");
    tft.print(knownIp);
    tft.setCursor(1,46);
    tft.print("AP Pass:");
    tft.print(apPass);
  }
  else {
    tft.print("IP: ");
    tft.print(knownIp);
    tft.setCursor(1,46);
    //tft.print("Signal Strength: ");
    //tft.print(i.wifi.signal);
    tft.print("Brightness: ");
    tft.print(((float(bri)/255)*100));
    tft.print("%");
  }

  // Third row with mode name
  tft.setCursor(1, 68);
  uint8_t qComma = 0;
  bool insideQuotes = false;
  uint8_t printedChars = 0;
  char singleJsonSymbol;
  // Find the mode name in JSON
  for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
    singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
    switch (singleJsonSymbol) {
    case '"':
      insideQuotes = !insideQuotes;
      break;
    case '[':
    case ']':
      break;
    case ',':
      qComma++;
    default:
      if (!insideQuotes || (qComma != knownMode))
        break;
      tft.print(singleJsonSymbol);
      printedChars++;
    }
    if ((qComma > knownMode) || (printedChars > tftcharwidth - 1))
      break;
  }
  // Fourth row with palette name
  tft.setCursor(1, 90);
  qComma = 0;
  insideQuotes = false;
  printedChars = 0;
  // Looking for palette name in JSON.
  for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
    singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
    switch (singleJsonSymbol) {
    case '"':
      insideQuotes = !insideQuotes;
      break;
    case '[':
    case ']':
      break;
    case ',':
      qComma++;
    default:
      if (!insideQuotes || (qComma != knownPalette))
        break;
      tft.print(singleJsonSymbol);
      printedChars++;
    }
    // The following is modified from the code from the u8g2/u8g8 based code (knownPalette was knownMode)
    if ((qComma > knownPalette) || (printedChars > tftcharwidth - 1))
      break;
  }
  // Fifth row with estimated mA usage
  tft.setCursor(1, 112);
  // Print estimated milliamp usage (must specify the LED type in LED prefs for this to be a reasonable estimate).
  tft.print(strip.currentMilliamps);
  tft.print("mA (estimated)");
  
}
