#include <SPI.h>
#include <SD.h>
#define CLK 2
#define DAT 8

const int BUF_SIZE = 11;
bool buffer[BUF_SIZE] = {0};
int pos = 0;
bool ignoreNext = false;
unsigned long lastRead = 0;
File root;
File myFile;

void setup() {
  Serial.begin(115200);
  pinMode(CLK, INPUT);
  pinMode(DAT, INPUT);
  attachInterrupt(digitalPinToInterrupt(CLK),readData , FALLING);
}

void loop() {
  if(pos != 0 && millis() - lastRead > 1000) {
    pos = 0;
  }
  if(pos == 11) {
    pos = 0;
    int keyCode = getKeyCode(buffer);
    if(ignoreNext) {
      ignoreNext = false;
      return;
    }
    if(keyCode == 0xF0) {
      ignoreNext = true;
      return;
    }
    Serial.write(keyCode);
  }
  int x = Serial.read();
  if(x==1)//LS
  {
  listfiles();
  x=-1;  
  }
  else if(x==2)//CAT
  {
    String plik="";
for(;;){if(Serial.available() > 0) {
plik = Serial.readStringUntil('\0');break;}}

cat(plik);

  }
  else if(x==3)//SAVING FILE
  {
    String plik="", content="";
for(;;){if(Serial.available() > 0) {plik = Serial.readStringUntil('\0');break;}}
for(;;){if(Serial.available() > 0) {content = Serial.readStringUntil('\0');break;}}

//Tutaj mamy przygotowane zmienne z nazwa pliku (plik) oraz z jego zawartoscia (content)
//Serial.print(plik);
//Serial.print("Ich bin da!\n\n\n");
//Serial.print(content);

save(plik, content);

  }
  else if(x==4)//REMOVE FILE
  {
    String plik="";
    for(;;){if(Serial.available() > 0) {plik = Serial.readStringUntil('\0');break;}}
    if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  SD.remove(plik);  
  }
 
}

void readData() {
  lastRead = millis();
  buffer[pos++ % 11] = digitalRead(DAT);
}

int getKeyCode(bool * buf) {
  bool parity = 1;
  int result = 0;
  if(buf[0] != 0) return -1;
  if(buf[10] != 1) return -2;
  for(int x = 0; x < 8; x++) {
    result |= buf[1+x] << x;
    if(buf[1+x]) parity = !parity;
  }

  if(buf[9] != parity) return -3;
  return result;
}

char getKeyChar(int keyCode) {
  switch(keyCode) {
    case 0x1C: return 'A';
    case 0x32: return 'B';
    case 0x21: return 'C';
    case 0x23: return 'D';
    case 0x24: return 'E';
    case 0x2B: return 'F';
    case 0x34: return 'G';
    case 0x33: return 'H';
    case 0x43: return 'I';
    case 0x3B: return 'J';
    case 0x42: return 'K';
    case 0x4B: return 'L';
    case 0x3A: return 'M';
    case 0x31: return 'N';
    case 0x44: return 'O';
    case 0x4D: return 'P';
    case 0x15: return 'Q';
    case 0x2D: return 'R';
    case 0x1B: return 'S';
    case 0x2C: return 'T';
    case 0x3C: return 'U';
    case 0x2A: return 'V';
    case 0x1D: return 'W';
    case 0x22: return 'X';
    case 0x35: return 'Y';
    case 0x1A: return 'Z';
    case 0x45: return '0';
    case 0x16: return '1';
    case 0x1E: return '2';
    case 0x26: return '3';
    case 0x25: return '4';
    case 0x2E: return '5';
    case 0x36: return '6';
    case 0x3D: return '7';
    case 0x3E: return '8';
    case 0x46: return '9';
    case 0x5A: return '\n';
    case 0x29: return ' ';
    case 0x66: return '\\';//«
    default: return '■';
  }

  return '\0';
}

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

void listfiles()
{
 /* while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }*/

  //Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization SD card failed!");
    while (1);
  }
  //Serial.println("initialization done.");

  root = SD.open("/");

  printDirectory(root, 0);
  Serial.print('\0');
  }

  void cat(String plik)
  {
    //Serial.print(plik);
    //Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  //Serial.println("initialization done.");

  // re-open the file for reading:
  myFile = SD.open(plik);
  if (myFile) {
    //Serial.println(plik);

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening file");
  }  Serial.print('\0');
  }

  void save(String plik, String content)
  {
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  //Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  SD.remove(plik);
  myFile = SD.open(plik, FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    //Serial.print("Writing to test.txt...");
    myFile.println(content);
    // close the file:
    myFile.close();
    //Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening file");
  }  
  }