#include <Arduino.h>
#include "xtensa/core-macros.h"
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>

#include "main.h"
#include "constants.h"
#include "congress.h"
#include "rain.h"
#include "supercomputer.h"
#include "cyber.h"
#include "flame.h"

#include "pillowlava8pt7b.h"

#define CYCLE_TIME_MS 20000

MatrixPanel_I2S_DMA *matrix = nullptr;

Mode mode = HighVis;
DisplayStyle style = Rain;

unsigned long last_switch;
bool cycling = true;

void setup(){
  pinMode(ONBOARD_LED, OUTPUT);
  pinMode(BACK_BUTTON, INPUT_PULLUP);
  pinMode(NEXT_BUTTON, INPUT_PULLUP);

  // redefine pins in constants.h if required
  HUB75_I2S_CFG::i2s_pins _pins={R1, G1, BL1, R2, G2, BL2, CH_A, CH_B, CH_C, CH_D, CH_E, LAT, OE, CLK};
  HUB75_I2S_CFG mxconfig(PANEL_WIDTH, PANEL_HEIGHT, PANELS_NUMBER, _pins);

  last_switch = millis();

  mxconfig.gpio.e = PIN_E;
  mxconfig.driver = HUB75_I2S_CFG::FM6126A;   // for panels using FM6126A chips

  mxconfig.latch_blanking = 4;
  mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M;
  mxconfig.clkphase = false;

  mxconfig.double_buff = true;

  matrix = new MatrixPanel_I2S_DMA(mxconfig);
  matrix->begin();
  matrix->setBrightness8(128);
  matrix->fillScreenRGB888(0, 0, 0);
  matrix->setTextWrap(false);
  matrix->setFont(&Pilowlava_Regular8pt7b);
}

void loop() {
  matrix ->flipDMABuffer();
  matrix->clearScreen();

  if (cycling and millis() - last_switch > CYCLE_TIME_MS) {
    // next style
    style = next_style(style); //DisplayStyle((style + 1) % (NumStyles - 1)); 
    last_switch = millis();
  }

  if(!digitalRead(BACK_BUTTON)) {
    switch(mode) {
      case Stealth:
        mode = LowVis;
        break;
      case LowVis:
        mode = HighVis;
        break;
      case HighVis:
        mode = Stealth;
        break;
    }
    while(!digitalRead(BACK_BUTTON)); // Wait for release
  }

  if(!digitalRead(NEXT_BUTTON)) {
    unsigned long pressed_at = millis();
    while(!digitalRead(NEXT_BUTTON)); // Wait for release
    // see if the button was held or tapped
    if (millis() - pressed_at > 500) {
        // todo
        cycling = not cycling;
    } else {
        style = next_style(style);
    }
  }

  switch(style) {
    case Rain:
      draw_rain(matrix, mode);
      break;
    case Congress:
      matrix->setFont(&Pilowlava_Regular8pt7b);
      draw_congress(matrix, mode);
      break;
    case Supercomputer:
      draw_supercomputer(matrix, mode);
      break;
    case Cyber:
      draw_cyber(matrix, mode);
      break;
    case Flame:
      draw_flame(matrix, mode);
      break;
  }
}

