 /**
-
+ * Put this file https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WebServer/examples/SDWebServer/SdRoot/edit/index.htm
+ * in the root folder of the SD card for webinterface
 */
 
+#include <ESP8266WiFi.h>
+#include <WiFiClient.h>
+#include <DNSServer.h>
+#include <ESP8266WebServer.h>
+#include <WiFiManager.h>
 #include <SPI.h>
 #include <MFRC522.h>
-
-//Add the SdFat Libraries
-#include <SdFat.h>
-#include <SdFatUtil.h>
-
-/*
-   For the RFID to work while MP3 plays, you have to change
-   #define USE_MP3_REFILL_MEANS USE_MP3_INTx
-   to
-   #define USE_MP3_REFILL_MEANS USE_MP3_Polled
-   in SFEMP3Shield.h
-*/
-#include <SFEMP3Shield.h>
-
-#define RST_PIN         5           // Configurable, see typical pin layout above
-#define SS_PIN          10          // Configurable, see typical pin layout above
-
-MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
+#include <Adafruit_VS1053.h>
+#include <SD.h>
+
+#define RC522_CS_PIN          D0
+#define SD_CS_PIN             D2
+
+#define BREAKOUT_RESET  D4     // VS1053 reset pin (output)
+#define BREAKOUT_CS     D8     // VS1053 chip select pin (output)
+#define BREAKOUT_DCS    D3    // VS1053 Data/command select pin (output)
+#define DREQ            D1    // VS1053 Data request, ideally an Interrupt pin
+
+Adafruit_VS1053_FilePlayer musicPlayer =
+  Adafruit_VS1053_FilePlayer(BREAKOUT_RESET, BREAKOUT_CS, BREAKOUT_DCS, DREQ, SD_CS_PIN);
+
+WiFiManager wifiManager;
+
+ESP8266WebServer server(80);
+
+MFRC522 mfrc522(RC522_CS_PIN, UINT8_MAX);   // Create MFRC522 instance.
 
 MFRC522::MIFARE_Key key;
 
 // Init array that will store new NUID
 byte nuidPICC[4];
 
-
-// Below is not needed if interrupt driven. Safe to remove if not using.
-#if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_Timer1
-#include <TimerOne.h>
-#elif defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
-#include <SimpleTimer.h>
-#endif
-
-SdFat sd;
-
-SFEMP3Shield MP3player;
+boolean playing = false;
+
+File currentFolder;
+
+File uploadFile;
+
 
 void setup() {
   Serial.begin(115200);
-  while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
-
-  //Initialize the SdCard.
-  if (!sd.begin(SD_SEL, SPI_FULL_SPEED)) sd.initErrorHalt();
-  // depending upon your SdCard environment, SPI_HAVE_SPEED may work better.
-  if (!sd.chdir("/")) sd.errorHalt("sd.chdir");
-
-  //Initialize the MP3 Player Shield
-  uint8_t result = MP3player.begin();
-  //check result, see readme for error codes.
-  if (result != 0) {
-    Serial.print(F("Error code: "));
-    Serial.print(result);
-    Serial.println(F(" when trying to start MP3 player"));
-    if ( result == 6 ) {
-      Serial.println(F("Warning: patch file not found, skipping.")); // can be removed for space, if needed.
-      Serial.println(F("Use the \"d\" command to verify SdCard can be read")); // can be removed for space, if needed.
-    }
-  }
 
   SPI.begin();        // Init SPI bus
   mfrc522.PCD_Init(); // Init MFRC522 card

    return;
  }

  if (mfrc522.uid.uidByte[0] == nuidPICC[0] &&
      mfrc522.uid.uidByte[1] == nuidPICC[1] &&
      mfrc522.uid.uidByte[2] == nuidPICC[2] &&
      mfrc522.uid.uidByte[3] == nuidPICC[3] ) {
    Serial.println(F("Card already read"));
    return;
  }

  // Store NUID into nuidPICC array
  for (byte i = 0; i < 4; i++) {
    nuidPICC[i] = mfrc522.uid.uidByte[i];
  }

  char folder[17];
  readBlock(1, 0, folder);
  Serial.print(F("Folder on rfid: "));
  Serial.println(folder);
  playFolder(folder);

  delay(100);
}

void readBlock(uint8_t sector, uint8_t relativeBlock, char *outputBuffer) {
  if (relativeBlock > 3) {
    Serial.println(F("Invalid block number"));
    return;
  }

  // Block 4 is trailer block

  }
}

void switchFolder(const char *folder) {
  // TODO do SD.exists(folder) check here, but it keeps crashing the ESP
  Serial.print(F("Switching folder to "));
  Serial.println(folder);
  currentFolder.close();
  currentFolder = SD.open(folder);
}

void stopMp3() {
    playing = false;
    musicPlayer.stopPlaying();
}

void playMp3() {
  while (File file = currentFolder.openNextFile())
  {

    char filename[30] = "";
    strcat(filename, "/");
    strcat(filename, currentFolder.name());
    strcat(filename, "/");
    strcat(filename, file.name());
    file.close();

    if(!file.isDirectory() && isMP3File(filename)){ 
      Serial.print(F("Playing "));
      Serial.println(filename);

      playing = true;
      musicPlayer.startPlayingFile(filename);
      return;
    } else {
      Serial.print(F("Ignoring "));
      Serial.println(filename);
    }
  }
  // Start again
  currentFolder.rewindDirectory();
}

bool isMP3File(const char* filename) {
  int   numChars;
  char  dotMP3[] = ".MP3";

  if (filename) {
    numChars = strlen(filename);
    if (numChars > 4) {
      byte index = 0;
      for (byte i = numChars - 4; i < numChars; i++) {
        if (!(toupper(filename[i]) == dotMP3[index])) {
          return false;
        }
        index++;
      }
      return true;
    }
  }
  return false;
}

void returnOK() {
  server.send(200, "text/plain", "");
}

void returnFail(String msg) {
  server.send(500, "text/plain", msg + "\r\n");
}

bool loadFromSdCard(String path){
  String dataType = "text/plain";
  if(path.endsWith("/")) path += "index.htm";

  if(path.endsWith(".htm")) dataType = "text/html";
  else if(path.endsWith(".css")) dataType = "text/css";
  else if(path.endsWith(".js")) dataType = "application/javascript";

  File dataFile = SD.open(path.c_str());
  if(dataFile.isDirectory()){
    path += "/index.htm";
    dataType = "text/html";
    dataFile = SD.open(path.c_str());
  }

  if (!dataFile)
    return false;

  if (server.hasArg("download")) dataType = "application/octet-stream";

  if (server.streamFile(dataFile, dataType) != dataFile.size()) {
    Serial.println("Sent less data than expected!");
  }

  dataFile.close();
  return true;
}

void handlePlayMp3() {
  playMp3();
  returnOK();
}

void handleStopMp3() {
  stopMp3();
  returnOK();
}
void handleFileUpload(){
  if(server.uri() != "/edit") return;
  HTTPUpload& upload = server.upload();
  if(upload.status == UPLOAD_FILE_START){
    if(SD.exists((char *)upload.filename.c_str())) SD.remove((char *)upload.filename.c_str());
    uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE);
    Serial.print("Upload: START, filename: "); Serial.println(upload.filename);
  } else if(upload.status == UPLOAD_FILE_WRITE){
    if(uploadFile) uploadFile.write(upload.buf, upload.currentSize);
    Serial.print("Upload: WRITE, Bytes: "); Serial.println(upload.currentSize);
  } else if(upload.status == UPLOAD_FILE_END){
    if(uploadFile) uploadFile.close();
    Serial.print("Upload: END, Size: "); Serial.println(upload.totalSize);
  }
}

void deleteRecursive(String path){
  File file = SD.open((char *)path.c_str());
  if(!file.isDirectory()){
    file.close();
    SD.remove((char *)path.c_str());
    return;
  }

  file.rewindDirectory();
  while(true) {
    File entry = file.openNextFile();
    if (!entry) break;
    String entryPath = path + "/" +entry.name();
    if(entry.isDirectory()){
      entry.close();
      deleteRecursive(entryPath);
    } else {
      entry.close();
      SD.remove((char *)entryPath.c_str());
    }
    yield();
  }

  SD.rmdir((char *)path.c_str());
  file.close();
}

void handleDelete(){
  if(server.args() == 0) return returnFail("BAD ARGS");
  String path = server.arg(0);
  if(path == "/" || !SD.exists((char *)path.c_str())) {
    returnFail("BAD PATH");
    return;
  }
  deleteRecursive(path);
  returnOK();
}

void handleCreate(){
  if(server.args() == 0) return returnFail("BAD ARGS");
  String path = server.arg(0);
  if(path == "/" || SD.exists((char *)path.c_str())) {
    returnFail("BAD PATH");
    return;
  }

  if(path.indexOf('.') > 0){
    File file = SD.open((char *)path.c_str(), FILE_WRITE);
    if(file){
      file.write((const char *)0);
      file.close();
    }
  } else {
    SD.mkdir((char *)path.c_str());
  }
  returnOK();
}

void printDirectory() {
  if(!server.hasArg("dir")) return returnFail("BAD ARGS");
  String path = server.arg("dir");
  if(path != "/" && !SD.exists((char *)path.c_str())) return returnFail("BAD PATH");
  File dir = SD.open((char *)path.c_str());
  path = String();
  if(!dir.isDirectory()){
    dir.close();
    return returnFail("NOT DIR");
  }
  dir.rewindDirectory();
  server.setContentLength(CONTENT_LENGTH_UNKNOWN);
  server.send(200, "text/json", "");
  WiFiClient client = server.client();

  server.sendContent("[");
  for (int cnt = 0; true; ++cnt) {
    File entry = dir.openNextFile();
    if (!entry)
    break;

    String output;
    if (cnt > 0)
      output = ',';

    output += "{\"type\":\"";
    output += (entry.isDirectory()) ? "dir" : "file";
    output += "\",\"name\":\"";
    output += entry.name();
    output += "\"";
    output += "}";
    server.sendContent(output);
    entry.close();
 }
 server.sendContent("]");
 dir.close();
}

void handleNotFound(){
  if(loadFromSdCard(server.uri())) return;
  String message = "SDCARD Not Detected\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  Serial.print(message);
}
