#include <Keyboard.h>
//#include <Adafruit_NeoPixel.h>

// Keys
//
#define KEY_KEYPAD_0        48
#define KEY_KEYPAD_1        49
#define KEY_KEYPAD_2        50
#define KEY_KEYPAD_3        51
#define KEY_KEYPAD_4        52
#define KEY_KEYPAD_5        53
#define KEY_KEYPAD_6        54
#define KEY_KEYPAD_7        55
#define KEY_KEYPAD_8        56
#define KEY_KEYPAD_9        57
#define KEY_KEYPAD_DECIMAL  60  // 46
#define KEY_KEYPAD_PLUS     223 // no
#define KEY_KEYPAD_MINUS    222 // 45
#define KEY_KEYPAD_MULTIPLY 221 // 42  // no
#define KEY_KEYPAD_DIVIDE   220 // 47
#define KEY_KEYPAD_NUMLOCK  -1
#define KEY_KEYPAD_EQUALS   10
#define DO_NOTHING          00

// int limite = 10; // Para probar los caracteres

// IO
byte cols[] = {9, 8, 7, 6};         // Entradas
byte rows[] = {18, 15, 14, 16, 10}; // Salidas
//byte ledPin = 5;
//byte ledCount = 17;

const int colCount = sizeof(cols) / sizeof(cols[0]);
const int rowCount = sizeof(rows) / sizeof(rows[0]);
//Adafruit_NeoPixel pixels(ledCount, ledPin, NEO_GRB + NEO_KHZ800);
/*
int layout[5][4] = {
  {61, 62, 63, 64},
  {65, 66, 67, 00},
  {68, 69, 70, 71},
  {72, 73, 74, 00},
  {75, 76, 77, 00}
};
*/
/*
// Switch Tester
int layout[5][4] = {
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0}
};
*/

// Layouts
int layout[5][4] = {
  {KEY_KEYPAD_NUMLOCK, KEY_KEYPAD_DIVIDE, KEY_KEYPAD_MULTIPLY, KEY_KEYPAD_MINUS},
  {KEY_KEYPAD_7, KEY_KEYPAD_8, KEY_KEYPAD_9, KEY_KEYPAD_0},
  {KEY_KEYPAD_4, KEY_KEYPAD_5, KEY_KEYPAD_6, KEY_KEYPAD_PLUS},
  {KEY_KEYPAD_1, KEY_KEYPAD_2, KEY_KEYPAD_3, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_DECIMAL, KEY_RETURN, KEY_KEYPAD_0}
};

/*
int layout[5][4] = {
  {KEY_KEYPAD_NUMLOCK, KEY_KEYPAD_DIVIDE, KEY_KEYPAD_DIVIDE, KEY_KEYPAD_MINUS},
  {KEY_KEYPAD_7, KEY_KEYPAD_8, KEY_KEYPAD_9, KEY_KEYPAD_DIVIDE},
  {KEY_KEYPAD_4, KEY_KEYPAD_5, KEY_KEYPAD_6, KEY_KEYPAD_DIVIDE},
  {KEY_KEYPAD_1, KEY_KEYPAD_2, KEY_KEYPAD_3, KEY_KEYPAD_DIVIDE},
  {KEY_KEYPAD_0, KEY_KEYPAD_DECIMAL, KEY_KEYPAD_DIVIDE, KEY_KEYPAD_DIVIDE}
};
*/

int shiftedLayout[5][4] = {
  {KEY_KEYPAD_NUMLOCK, KEY_KEYPAD_DIVIDE, KEY_KEYPAD_MULTIPLY, KEY_KEYPAD_MINUS},
  {KEY_HOME, KEY_UP_ARROW, KEY_PAGE_UP, DO_NOTHING},
  {KEY_LEFT_ARROW, DO_NOTHING, KEY_RIGHT_ARROW, KEY_KEYPAD_PLUS},
  {KEY_END, KEY_DOWN_ARROW, KEY_PAGE_DOWN, DO_NOTHING},
  {KEY_INSERT, KEY_DELETE, KEY_RETURN, KEY_KEYPAD_0}
};

/*
int shiftedLayout[5][4] = {
  {KEY_KEYPAD_NUMLOCK, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0},
  {KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0, KEY_KEYPAD_0}
};
*/

int currentLayout[5][4];

/*
char layout[5][4] = {
  {'b', '/', '*', '-'},
  {'7', '8', '9', 'x'},
  {'4', '5', '6', '+'},
  {'1', '2', '3', 'x'},
  {'0', '.', 'e', 'x'}
};
*/
int longPressDelay = 350;
int spamSpeed = 15;

int keyDown[5][4];
bool keyLong[5][4];

bool shifted = false;

void setup() {
  // currentLayout = layout;

  memcpy(currentLayout, layout, sizeof(layout));
  
  for (int i = 0; i < colCount; i++) {
    pinMode(cols[i], INPUT_PULLUP);
  }
  for (int i = 0; i < rowCount; i++) {
    pinMode(rows[i], OUTPUT);
    digitalWrite(rows[i], HIGH);
  }
  //pinMode(ledPin, OUTPUT);

  Keyboard.begin();

  //pixels.begin();

  //for (int i = 0; i < ledCount; i++) {
  //  pixels.setPixelColor(i, 50, 50, 50);
  //}
  //pixels.show();
}

void loop() {
  /*
  if (digitalRead(9) == LOW) {
    //Keyboard.println("Pulsador izquierdo pulsado: Copiar");
    //delay(200);
    /*
    for (int i = 0; i < limite; i++) {
//      int character = i + (limite - 10);
      Keyboard.println("Character: ");
//      Keyboard.write(character);
//      Keyboard.println("");
    }
    Keyboard.println("Done!");
    delay(1000);
    limite += 10;
    */
//  }
  

  for (int i = 0; i < rowCount; i++) {
    digitalWrite(rows[i], LOW);
    delayMicroseconds(5);
  
    for (int j = 0; j < colCount; j++) {
      if (digitalRead(cols[j]) == LOW) {
        keyPressed(i, j);
      } else if (keyDown[i][j] != 0) {
        resetKey(i, j);
      }
    }

    digitalWrite(rows[i], HIGH);
    delayMicroseconds(500);
  }
  
}

void keyPressed(int row, int col) {
  if (keyDown[row][col] == 0) {
    if (currentLayout[row][col] == KEY_KEYPAD_NUMLOCK) {
      // currentLayout = (currentLayout == layout) ? shiftedLayout : layout;
      if (shifted){
        shifted = false;
        memcpy(currentLayout, layout, sizeof(layout));
      } else {
        shifted = true;
        memcpy(currentLayout, shiftedLayout, sizeof(shiftedLayout));
      }
    } else {
      Keyboard.write(currentLayout[row][col]); 
    }
  } else if (keyLong[row][col] && keyDown[row][col] > spamSpeed) {
    if (currentLayout[row][col] == KEY_KEYPAD_NUMLOCK) {
      // currentLayout = (currentLayout == layout) ? shiftedLayout : layout;
      if (shifted){
        shifted = false;
        memcpy(currentLayout, layout, sizeof(layout));
      } else {
        shifted = true;
        memcpy(currentLayout, shiftedLayout, sizeof(shiftedLayout));
      }
    } else {
      Keyboard.write(currentLayout[row][col]);
      keyDown[row][col] = 1;
    }
  } else if (keyDown[row][col] > longPressDelay) {
    keyLong[row][col] = true;
  }

  keyDown[row][col]++;
}

void resetKey(int row, int col) {
  keyDown[row][col] = 0;
  keyLong[row][col] = false;
}
