//source: https://editor.soulmatelights.com/gallery/834-munch-2

#include "FastLED.h"
#define DATA_PIN 2
#define BRIGHTNESS 255
#define NUM_LEDS 256
#define LED_COLS 16
#define LED_ROWS 16
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
//#define FRAMES_PER_SECOND 60
const uint8_t kMatrixWidth = 16;
const uint8_t kMatrixHeight = 16;

const bool    kMatrixSerpentineLayout = false;

#define WIDTH LED_COLS
#define HEIGHT LED_ROWS

const byte maxDim = max(WIDTH, HEIGHT);
const byte minDim = min(WIDTH, HEIGHT);
const byte width_adj = (WIDTH < HEIGHT ? (HEIGHT - WIDTH) / 2 : 0);
const byte height_adj = (HEIGHT < WIDTH ? (WIDTH - HEIGHT) / 2 : 0);
const byte maxDim_steps = 256 / max(WIDTH, HEIGHT);

byte randz = 4; //1-8 

void setup() {
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS); //setCorrection(TypicalLEDStrip);
  //FastLED.addLeds<LED_TYPE,DATA_PIN,CLK_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
 //Serial.begin(115200);
}

class EffectMunch {
  private:
    byte count = 0;
  int16_t dir = 1;
  byte flip = 0;
  byte generation = 0;
  byte mic[2];
  bool flag = false;
  
  
  bool munchRoutine();
  
  public:
    byte minDimLocal = maxDim > 32 ? 32 : 16;
  bool run();
  void load();
};

bool EffectMunch::run() {
  CRGB color;
  for (byte x = 0; x < minDimLocal; x++) {
    for (byte y = 0; y < minDimLocal; y++) {
      color = (x ^ y ^ flip) < count ? ColorFromPalette(RainbowColors_p, ((x ^ y) << randz) + generation) : CRGB::Black;
      if (x < WIDTH and y < HEIGHT) leds[XY(x, y)] = color;
      if (x + minDimLocal < WIDTH and y < HEIGHT) leds[XY(x + minDimLocal, y)] = color;
      if (y + minDimLocal < HEIGHT and x < WIDTH) leds[XY(x, y + minDimLocal)] = color;
      if (x + minDimLocal < WIDTH and y + minDimLocal < HEIGHT) leds[XY(x + minDimLocal, y + minDimLocal)] = color;
      
    }
  }
  
  
  count += dir;
  
  if (count <= 0 || count >= mic[0]) {
    dir = -dir;
    if (count <= 0) {
      mic[0] = mic[1];
      if (flip == 0)
        flip = mic[1] - 1;
      else
        flip = 0;
    }
  }
  
  generation++;
  #ifdef MIC_EFFECTS
  mic[1] = isMicOn() ? map(getMicMapMaxPeak(), 0, 255, 0, minDimLocal) : minDimLocal;
  #else
  mic[1] = minDimLocal;
  #endif
  return true;
}
EffectMunch eff;

void loop() 
{
  eff.run();
  delay(16); // ~60Fps
      FastLED.show();

}
 
uint16_t XY( uint8_t x, uint8_t y)
{
  uint16_t i;
  if( kMatrixSerpentineLayout == false) {
    i = (y * kMatrixWidth) + x;
  }
  if( kMatrixSerpentineLayout == true) {
    if( y & 0x01) {
      // Odd rows run backwards
      uint8_t reverseX = (kMatrixWidth - 1) - x;
      i = (y * kMatrixWidth) + reverseX;
    } else {
      // Even rows run forwards
      i = (y * kMatrixWidth) + x;
    }
  }
  return i;
}