/*
 * dfPlayer auf Wemos D1: https://forum.arduino.cc/t/dfplayer-mini-mit-wemos-d1-uno/677980/3
 * Details dfPlayer: https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299#target_3
 *                   https://wolles-elektronikkiste.de/dfplayer-mini-ansteuerung-mit-dem-arduino
 * W5500 Ethernet Shield: https://www.arduino.cc/en/Tutorial/LibraryExamples/WebServer
 */

#include "DFRobotDFPlayerMini.h"
#include "ESP8266WiFi.h"

#include <SPI.h>
#include <Ethernet.h>


DFRobotDFPlayerMini dfPlayer;
int volume = 22;

//byte mac[] = { 0x02, 0x60, 0x0D, 0xF0, 0x0D, 0x04 };
byte mac[] = { 0x80, 0x7d, 0x3a, 0x66, 0xd1, 0x62 };
IPAddress ip(192, 168, 178, 60);
EthernetServer server(80);

String header;
String body;
unsigned long lastring = 0;

void setup() {
  WiFi.mode(WIFI_OFF);

  Serial.begin(115200);
  Serial.println();
  Serial.println("Starting server");

  Serial1.begin(9600);// TX liegt auf Pin D4 RX geht nicht !!
  dfPlayer.begin(Serial1);
  delay(100);
  dfPlayer.setTimeOut(500); // Set serial communication time out 500ms
  dfPlayer.volume(volume);  // Set volume value (0~30).
  dfPlayer.EQ(DFPLAYER_EQ_NORMAL);
  dfPlayer.outputDevice(DFPLAYER_DEVICE_SD);

  Ethernet.init(5); // W5500 CS PIN auf D1
  Ethernet.begin(mac, ip);

  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield not found");
    dfPlayer.play(3);
    while (true) {
      delay(5000);
    }
  }
  
  while (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected");
    delay(5000);
  }
  
  server.begin();
  Serial.println(Ethernet.localIP());

  dfPlayer.play(2);
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    bool currentLineIsBlank = true;

    byte trigger = 0;
    char uri[64];
    byte idx = 0;
    boolean uriLine = false;

    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        if (currentLineIsBlank && c == 'G') {
          uriLine = true;
          uri[idx] = c;
          idx++;
        }
        else if (uriLine) {
          if (c == '\n') {
            uriLine = false;
            uri[idx] = '\0';
          }
          else {
            uri[idx] = c;
            idx++;
          }
        }

        Serial.write(c);
        header += c;
        
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          if (header.indexOf("GET /status") >= 0) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type: application/json; charset=utf-8");
            client.println("Connection: close");
            client.println();
            client.println("{");
            client.println("  \"online\": true,");
            client.print("  \"volume\": ");
            client.print(volume);
            client.println(",");
            client.print("  \"lastring\": ");
            if (lastring <= 0) {
              client.println(-1);
            }
            else {
              client.println(millis() - lastring);
            }
            client.println("}");
            break;
          }
          else if (header.indexOf("PUT /volume") >= 0) {
            while (client.connected()) {
              char c = client.read();
              body += c;
              if (c == '}') {
                break;
              }
            }
            
            String str1 = body;
            str1 = str1.substring(str1.indexOf("value"));
            str1 = str1.substring(str1.indexOf(":") + 1);
            while (str1.length() > 0 && str1.startsWith(" ")) {
              str1 = str1.substring(1);
            }

            int ix = 0;
            while (isDigit(str1.charAt(ix))) {
              ix++;
            }

            if (ix > 0) {
              volume = str1.substring(0, ix).toInt();
              if (volume < 0) {
                volume = 0;
              }
              else if (volume > 30) {
                volume = 30;
              }
              
              dfPlayer.volume(volume);
              Serial.print("Volume set to ");
              Serial.println(volume);
              
              client.println("HTTP/1.1 200 OK");
            }
            else {
              client.println("HTTP/1.1 400 Bad Request");                  
            }
            
            client.println("Connection: close");
            break;
          }
          
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-type: text/html; charset=utf-8");
          client.println("Connection: close");
          client.println();
          
          // turns the GPIOs on and off
          if (header.indexOf("GET /bell/on") >= 0) {
            dfPlayer.play(1);  // play the first mp3
            lastring = millis();
          }
          else if (header.indexOf("GET /setvolume/") >= 0) { // yes, I know this is not RESTful
            String str1 = header;
            str1 = str1.substring(header.indexOf("GET /setvolume/") + 15);
            volume = str1.substring(0, str1.indexOf(" ")).toInt();
            
            if (volume < 0) {
              volume = 0;
            }
            else if (volume > 30) {
              volume = 30;
            }
            
            dfPlayer.volume(volume);
            Serial.print("Volume set to ");
            Serial.println(volume);
          }

          // Display the HTML web page
          client.println("<!DOCTYPE html><html>");
          client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
          client.println("<link rel=\"icon\" href=\"data:,\">");
          client.println("<style>html { font-family: sans-serif; display: inline-block; margin: 0px auto; text-align: center; }");
          client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
          client.println(".button2 { background-color: #4CAF50; border: none; color: white; padding: 4px 10px; text-decoration: none; margin: 1px; cursor: pointer;}</style></head>");
          
          client.println("<body><h1>LeWe T&uuml;rklingel</h1>");
          client.println("<p>Volume: <a href=\"/setvolume/" + String(volume-1) + "\"><button class=\"button2\">&minus;</button></a> " + String(volume) + " <a href=\"/setvolume/" + String(volume+1) + "\"><button class=\"button2\">&plus;</button></a></p>");
          client.println("<p><a href=\"/bell/on\"><button class=\"button\">Klingeln</button></a></p>");
          client.println("</body></html>");
          
          // The HTTP response ends with another blank line
          client.println();
          
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    
    header = "";
    body = "";
    
    // give the web browser time to receive the data
    delay(10);
    client.stop();
    Serial.println("Client disconnected");
  }
}
