#pragma once

int dataPin = 12;
int clockPin = 11;
int csPin = 10;

typedef enum MaxRegister {
    scanLimit = 0x0B,
    intensity = 0x0A,
    decode = 0x09,
    shotDown = 0x0c
} MaxRegister;

void softwareSPI(uint8_t A, uint8_t B) {  
    digitalWrite(csPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, A);
    shiftOut(dataPin, clockPin, MSBFIRST, B);  
    digitalWrite(csPin, HIGH);
}

void displayClear() {
  for (int i = 0; i < 8; i++) {
    softwareSPI(i, 0);
  }
}

void displayInit() {
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
    pinMode(csPin, OUTPUT);
    digitalWrite(csPin, HIGH);  
  
    // Выставляем scanLimit на максимум (таблица 8) - это количество колонок матрицы по умолчанию горела бы только одна колонка      
    softwareSPI(MaxRegister::scanLimit, 0x07);  

	  // Выставляем intensity согласно (таблице 7)  
    softwareSPI(MaxRegister::intensity, 0x0F);
  
    // отключаем decode-mode, если он вдруг включен (таблица 4)  
    softwareSPI(MaxRegister::decode, 0x00);
  
    // Очищаем дисплей. Документация про это умалчивает, но в SRAM при запуске лежит мусор  
    displayClear();
  
    // теперь выходим в рабочий режим (таблица 3) и рисуем что хотим.  
    softwareSPI(MaxRegister::shotDown, 0x01);  
}

byte leds[8] = {0b00000001, 0b00000010, 0b00000100, 0b00001000, 0b00010000, 0b00100000, 0b01000000, 0b10000000};
byte strings[8] = {0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000};

typedef struct {
  int x;
  int y;
} Point;

typedef struct {
  int size;
  Point points[];
} Snake;

typedef struct {
  int prev;
  int curr;
} Button;

Snake snake;
Button buttons[4] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};

void high(int row, int col) {
  strings[row - 1] = strings[row - 1] | leds[col - 1];
  softwareSPI(row, strings[row - 1]);
}

void low(int row, int col) {
  strings[row - 1] = strings[row - 1] & ~leds[col - 1];
  softwareSPI(row, strings[row - 1]);
}

void myClearDisplay() {
  for (int i = 0; i < 8; i++) {
    softwareSPI(i, 0);
    strings[i] = strings[i] & 0b00000000;
  }
  softwareSPI(8, 0);
}

void drawSnake() {
  for (int i = 0; i < snake.size; i++) {
    high(snake.points[i].x, snake.points[i].y);
  }
}

/*void controller() {
  // up button
  buttons[0].curr = digitalRead(2);
  if (buttons[0].curr && !buttons[0].prev) {
    if (snake.x == 1) {
      snake.x = 8;
    }
    else {
      snake.x = snake.x - 1;
    }
  }
  // left button
  buttons[1].curr = digitalRead(3);
  if (buttons[1].curr && !buttons[1].prev) {
    if (snake.y == 1) {
      snake.y = 8;
    }
    else {
      snake.y = snake.y - 1;
    }
  }
  // right button
  buttons[2].curr = digitalRead(4);
  if (buttons[2].curr && !buttons[2].prev) {
    if (snake.y == 8) {
      snake.y = 1;
    }
    else {
      snake.y = snake.y + 1;
    }
  }
  // down button
  buttons[3].curr = digitalRead(5);
  if (buttons[3].curr && !buttons[3].prev) {
    if (snake.x == 8) {
      snake.x = 1;
    }
    else {
      snake.x = snake.x + 1;
    }
  }
  buttons[0].prev = buttons[0].curr;
  buttons[1].prev = buttons[1].curr;
  buttons[2].prev = buttons[2].curr;
  buttons[3].prev = buttons[3].curr;
}*/

void setup() {
  displayInit();
  snake.size = 1;
  snake.points[0] = {3, 4};
  //snake.points[1] = {4, 4};
  //snake.points[2] = {5, 4};
  //snake.points[3] = {6, 4};
  pinMode(2, INPUT); // up button
  pinMode(3, INPUT); // left button
  pinMode(4, INPUT); // right button
  pinMode(5, INPUT); // down button
  Serial.begin(9600);
}

void loop() {
  //drawSnake();
  Serial.println(snake.points[0].x);
}