#include <FastLED.h>
#define LED_PIN  2
#define COLOR_ORDER GRB
#define CHIPSET     WS2812B
#define BRIGHTNESS 255
#define FASTLED_SHOW_CORE 0  // -- The core to run FastLED.show()

// -- Task handles for use in the notifications
static TaskHandle_t FastLEDshowTaskHandle = 0;
static TaskHandle_t userTaskHandle = 0;

/** show() for ESP32
 *  Call this function instead of FastLED.show(). It signals core 0 to issue a show, 
 *  then waits for a notification that it is done.
 */
void FastLEDshowESP32()
{
    if (userTaskHandle == 0) {
        // -- Store the handle of the current task, so that the show task can
        //    notify it when it's done
        userTaskHandle = xTaskGetCurrentTaskHandle();

        // -- Trigger the show task
        xTaskNotifyGive(FastLEDshowTaskHandle);

        // -- Wait to be notified that it's done
        const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 200 );
        ulTaskNotifyTake(pdTRUE, xMaxBlockTime);
        userTaskHandle = 0;
    }
}

/** show Task
 *  This function runs on core 0 and just waits for requests to call FastLED.show()
 */
void FastLEDshowTask(void *pvParameters)
{
    // -- Run forever...
    for(;;) {
        // -- Wait for the trigger
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        // -- Do the show (synchronously)
        FastLED.show();        
        

        // -- Notify the calling task
        xTaskNotifyGive(userTaskHandle);
    }
}

// Digitos
int digit[10][16][8]= {
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,0,1,0,0,1,0,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,0,0,0},{0,1,1,0,0,0,0,0},{0,1,1,0,0,0,0,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,1,1,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,0,0,1,0,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,1,1,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,1,1,0,0,0,0,0},{0,1,1,0,0,0,0,0},{0,1,1,1,1,0,0,0},{0,0,1,1,1,1,0,0},{0,0,0,1,1,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,1,1,0,0,0,0,0},{0,1,1,0,0,0,0,0},{0,1,1,1,1,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           {{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,1,1,1,1,0,0},{0,1,1,1,1,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,1,1,1,1,0},{0,0,0,0,0,1,1,0},{0,0,0,0,0,1,1,0},{0,1,1,1,1,1,1,0},{0,0,1,1,1,1,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}},
                           };

// tempos

int t_ms=0; 
int t_s=0, t_m=0, t_h=0;
int j=0;
int i=0;
unsigned long startTime = 0;

// Color
byte cor =180;

// Params for width and height
const uint8_t kMatrixWidth = 32;
const uint8_t kMatrixHeight = 16;

// Param for different pixel layouts
const bool    kMatrixSerpentineLayout = true;

/*
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;
}
*/

uint16_t XY( uint8_t x, uint8_t y)
{
  uint16_t i;

  if( kMatrixSerpentineLayout == false) {
    i = (y * kMatrixHeight) + x;
  }

  if( kMatrixSerpentineLayout == true) {
    if( y & 0x01) {
      // Odd collumns run backwards
      uint8_t reverseY = (kMatrixHeight - 1) - x;
      i = (y * kMatrixHeight) + reverseY;
    } else {
      // Even Collumns run forwards
      i = (y * kMatrixHeight) + x;
    }
  }

  return i;
}


#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
CRGB leds_plus_safety_pixel[ NUM_LEDS + 1];
CRGB leds[NUM_LEDS];

uint16_t XYsafe( uint8_t x, uint8_t y)
{
  if( x >= kMatrixWidth) return -1;
  if( y >= kMatrixHeight) return -1;
  return XY(x,y);
}

// Demo that USES "XY" follows code below

void setup() {
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);//.setCorrection(TypicalSMD5050);
  FastLED.setBrightness( BRIGHTNESS );
  //Serial.begin(115200);
 	// -- Create the ESP32 FastLED show task
  xTaskCreatePinnedToCore(FastLEDshowTask, "FastLEDshowTask", 2048, NULL, 2, &FastLEDshowTaskHandle, FASTLED_SHOW_CORE); 

    for (int j=0; j<256; j++){
        leds[j] = CRGB::Black;
    }
}

void loop()
{
  /*
EVERY_N_MILLISECONDS(10){
  
  

  if (t_s==512){
    t_s = 0;
  }
  leds[t_s] = CHSV(180,255,255); 
  FastLEDshowESP32();

  t_s++; 
}  
*/

Relogio();

/*
EVERY_N_MILLISECONDS(10){

if (t_s == 16) {
  t_s = 0;
  j++;
}
if (j==32) {
  j=0;
      for (int j=0; j<512; j++){
        leds[j] = CRGB::Black;
    }
}
cor++;
leds[XY(t_s,j)] = CHSV(cor,255,255);   


t_s++;

FastLEDshowESP32();
}
*/
}

void Relogio ()
{

    EVERY_N_MILLISECONDS(500){
      t_s++;    
    if (t_s==1){
      t_m++;
      t_s=0;
    }
    if (t_m==60){
      t_h++;
      t_m=0;
    }
    if (t_h==24){
      t_h=0;
    }
 int Dm2 = t_m % 10;
 int Dm1 = t_m / 10;
 int Dh2 = t_h % 10;
 int Dh1 = t_h / 10;
 
//Serial.println(t_s);

 PrintDisplay(Dh1,Dh2,Dm1,Dm2);
  }

}


void PrintDisplay (int h1, int h2, int m1, int m2){
  int bri = 255;
  

    for (int i=0; i<16; i++){
    for (int j=0; j<32; j++){
        leds[XY(i,j)] = CRGB::Black;
    }
    }
//Serial.println(t_ms+1);
  for (int i=0; i<16; i++){
    for (int j=0; j<8; j++){
      leds[XY(i,j)] = CHSV(cor,255,bri*digit[h1][15-i][j]);      
    }
  }
//Serial.println(t_ms+2);  
  for (int i=0; i<16; i++){
    for (int j=7; j<15; j++){
      leds[XY(i,j)] = CHSV(cor,255,bri*digit[h2][15-i][(j-7)]);    
    }
  }
//Serial.println(t_ms+3);
  for (int i=0; i<16; i++){
    for (int j=17; j<25; j++){
      leds[XY(i,j)] = CHSV(cor,255,bri*digit[m1][15-i][(j-17)]);      
    }
  }
//Serial.println(t_ms+4);
  for (int i=0; i<16; i++){
    for (int j=24; j<32; j++){
      leds[XY(i,j)] = CHSV(cor,255,bri*digit[m2][15-i][(j-24)]);      
    }
  }
//Serial.println(t_ms+5);




  leds[XY(4,15)] = CHSV(cor,255,bri); 
  leds[XY(4,16)] = CHSV(cor,255,bri); 
  leds[XY(5,15)] = CHSV(cor,255,bri); 
  leds[XY(5,16)] = CHSV(cor,255,bri); 

  leds[XY(9,15)] = CHSV(cor,255,bri); 
  leds[XY(9,16)] = CHSV(cor,255,bri); 
  leds[XY(10,15)] = CHSV(cor,255,bri); 
  leds[XY(10,16)] = CHSV(cor,255,bri); 

  
  FastLEDshowESP32();

  cor++;


/*
  //startTime = millis();
  while (millis() < startTime+1000) {
  // do something here while we are waiting
  

  leds[XY(15,4)] = CHSV(cor,120,bri); 
  leds[XY(16,4)] = CHSV(cor,120,bri); 
  leds[XY(15,5)] = CHSV(cor,120,bri); 
  leds[XY(16,5)] = CHSV(cor,120,bri); 

  leds[XY(15,9)] = CHSV(cor,120,bri); 
  leds[XY(16,9)] = CHSV(cor,120,bri); 
  leds[XY(15,10)] = CHSV(cor,120,bri); 
  leds[XY(16,10)] = CHSV(cor,120,bri); 
  
  
  FastLEDshowESP32();
  }
*/   
  //delay(10);
//Serial.println(t_ms+9);  
}