#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include <Fonts/FreeMono9pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>


// PINOUT
#define LED_MATRIX_CONTROL_PIN 3
#define INCREMENT_BUTTON_PIN   4
#define RESET_BUTTON_PIN       5

#define INCREMENT_SENSITIVITY_MILLIS  100
#define RESET_SENSITIVITY_MILLIS     5000

// STATUS BUTTON
#define BUTTON_PUSH 0
#define BUTTON_IDLE 1


// MATRIX DECLARATION:
// Parameter 1 = width of NeoPixel matrix
// Parameter 2 = height of matrix
// Parameter 3 = pin number (most are valid)
// Parameter 4 = matrix layout flags, add together as needed:
//   NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
//     Position of the FIRST LED in the matrix; pick two, e.g.
//     NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
//   NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
//     rows or in vertical columns, respectively; pick one or the other.
//   NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
//     in the same order, or alternate lines reverse direction; pick one.
//   See example below for these values in action.
// Parameter 5 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(48, 16, LED_MATRIX_CONTROL_PIN,
  NEO_MATRIX_BOTTOM    + NEO_MATRIX_RIGHT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_GRB            + NEO_KHZ800);

const uint16_t color = matrix.Color(255, 16, 16);

uint16_t counter;

uint32_t increment_pressed_millis;
uint32_t reset_pressed_millis;

uint8_t increment_release;
uint8_t reset_release;


void print_count()
{
  if(counter <= 999){
    if(counter == 0)
      matrix.setFont(&FreeMonoBold12pt7b);

      matrix.setCursor(2, 15);

  }else{
    if(counter == 1000)
      matrix.setFont(&FreeMono9pt7b);

      matrix.setCursor(2, 13);
  }

  matrix.fillScreen(0);
  matrix.print(counter);

  matrix.show();
}


void setup()
{
    pinMode(INCREMENT_BUTTON_PIN, INPUT_PULLUP);
    pinMode(RESET_BUTTON_PIN, INPUT_PULLUP);

    matrix.begin();
    matrix.setTextWrap(false);
    matrix.setBrightness(100);
    matrix.setTextColor(color);

    print_count();
}


void loop()
{
    // Interruptor de incremento  
    if(digitalRead(INCREMENT_BUTTON_PIN) == BUTTON_PUSH){
        if(increment_pressed_millis == 0)
            increment_pressed_millis = millis();

        // Se supero INCREMENT_SENSITIVITY_MILLIS
        if (millis() >= (increment_pressed_millis + INCREMENT_SENSITIVITY_MILLIS) && increment_release == 0){
            increment_release = 1;
            counter++;

            print_count();
        }

    }else{
        increment_release        = 0;
        increment_pressed_millis = 0;
    }


    // Botón de Reseteo
    if(digitalRead(RESET_BUTTON_PIN) == BUTTON_PUSH){
        if(reset_pressed_millis == 0)
            reset_pressed_millis = millis();

        // Se supero RESET_SENSITIVITY_MILLIS
        if (millis() >= (reset_pressed_millis + RESET_SENSITIVITY_MILLIS) && reset_release == 0){
            reset_release = 1;
            counter       = 0;

            print_count();
        }

    }else{
        reset_release        = 0;
        reset_pressed_millis = 0;
    }
}
