#include <LiquidCrystal.h>
#include <LCD_Key.h>
#include "SdFat.h"

               // RS, E, DB4, DB5, DB6, DB7
LiquidCrystal lcd(8,  9,  4,   5,   6,   7);
LCD_Key keypad;

const uint8_t SD_CS_PIN = 3;

#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI) 

SdFat32 sd;
File32 root;
File32 dir;
File32 file; 
int FileNumber=0;
int DirNumber=0;
uint16_t idx;
uint16_t diridx=1;

void printDisplay(String message){
  clearLine(1);
  lcd.setCursor(0, 1);
  lcd.print(message);
  delay(1000);
  clearLine(1);
}

void clearLine(int line){
  lcd.setCursor(0, line);
  lcd.print("                ");
  lcd.setCursor(0, line);
}

void DisplayFile(FatFile &file, int FileNumber){
  char arr[31];
  file.getName(arr, 31); 
         
  clearLine(0); byte n=lcd.print(FileNumber);

  if(file.isDir()) {
    lcd.print(":");
    n++;
  }
  
  lcd.print(' '); file.printName(&lcd);

  clearLine(1); 
  for (int i=15-n; i<strlen(arr); i++)
  lcd.print(arr[i]);
             
} // end DisplayFile() *******************************************************

void PreviousFile() {
 
  if (FileNumber <= 1){
    FileNumber=0;
    dir.rewindDirectory();
    DisplayFile(dir, DirNumber);
    return; 
  }


  for (uint16_t i = idx-1; i >=0; i--) {

    if (file.open(&dir, i, O_RDONLY) && file.isFile() && !file.isHidden()){
       FileNumber--;
       idx=i;
       DisplayFile(file, FileNumber);
       file.close();
       return;
    }
    file.close();
  }
  
} // end PreviousFile() *******************************************************

void NextFile(){

    while (file.openNext(&dir, O_RDONLY)) {
   
      
      if (file.isFile() && !file.isHidden()){
        FileNumber++;
        
        idx=file.dirIndex();
        
        DisplayFile(file, FileNumber);
      
        file.close();
        return;
      }  
    file.close();
    }

} // end NextFile() *******************************************************


void NextDir(){
  
  dir.close();

  while (dir.openNext(&root, O_RDONLY)) {
      if (dir.isDir() && !dir.isHidden()){
        DirNumber++;
        DisplayFile(dir, DirNumber);
        diridx=dir.dirIndex();
        FileNumber=0;
        return;
      }  
      dir.close();
    }
    dir.open(&root, diridx, O_RDONLY);

} // end NextDir() *******************************************************



void PreviousDir(){
  
  if (DirNumber == 0) return;
      
  dir.close();
  
  if (DirNumber == 1) {
     dir.open("/", O_READ);
     DirNumber=0;
     FileNumber=0;
     root.rewindDirectory();
     DisplayFile(dir, DirNumber);
     return;
  }
    
  for (uint16_t i = diridx-1;i >=0; i--) {
    if (dir.open(&root, i, O_RDONLY) && dir.isDir() && !dir.isHidden()){
       DirNumber--;
       diridx=i;
       DisplayFile(dir, DirNumber);
       FileNumber=0;
       return;
    }
    dir.close();
  
  }
  
} // end PreviousDir() *******************************************************

void PlotFile() {

  char shortname[13];
  char str[127];
 
  file.open(&dir, idx, O_RDONLY);
  
  file.getSFN(shortname);
  int8_t len = strlen(shortname);
  if (!strstr( strlwr(shortname + (len - 3) ),".nc")) {
      printDisplay("Not G-code");
      file.close();
      return;
  }    
      
  lcd.blink();

  for (int i=0;i<2 && file.available(); i++){
     file.fgets(str,127);
     Serial.println(str);
    
  }
  

  while (file.available()) {
    file.fgets(str,127);
    Serial.println(str);
    
    while(!Serial.available());
    while(Serial.available()) {
        Serial.read();
        delay(1);
    }
  }

   lcd.noBlink();
   
   file.close();
   
} // end PlotFile *******************************************************



void setup() {
  Serial.begin(115200);
 
  while(!Serial);
  
  if (!sd.begin(SD_CONFIG)) sd.initErrorHalt(); 
  
  dir.open("/", O_READ);
  root.open("/", O_READ);
  
  
  lcd.begin(16, 2);
  
  analogWrite(10,70);

  keypad.setRate(20);

  DisplayFile(dir, DirNumber); 
  NextFile(); 

} // end setup *******************************************************


void loop() {
    
  #define delay_ms 450

  switch (keypad.getKey()) {
    
    case UP_KEY:
      PreviousFile();
      delay(delay_ms);
      break;

    case DOWN_KEY:
      NextFile();
      delay(delay_ms);
      break;
    
    case LEFT_KEY:
      PreviousDir();
      delay(delay_ms);
      break;
    
    case RIGHT_KEY:
      NextDir();
      delay(delay_ms);
      break;
    
    case SELECT_KEY:
      if(FileNumber) PlotFile();
      delay(delay_ms);
 }
} // end loop *******************************************************
