/*
 *  RESTful Wake On Lan 
 *  Author: Toby Chui
 * 
 *  This firmware provide a web interface / RESTFUL API
 *  request for remote power-on / off or reset your computer
 *  by emulating button press on the front-panel headers
 *  
 *  The following firmware config are recommended
 *  Board: Wemos D1 Mini
 *  CPU clockspeed: 160Mhz
 *  IwIP Varient: v2 Higher Bandwidth
 * 
 */

#include <ESP8266WiFi.h>        
#include <WiFiManager.h>
#include <ESP8266mDNS.h>
#include <ArduinoJson.h>
#include <LittleFS.h>

/* Pin Definations */
//On-board Programmable Button
#define BTN_INPUT D0 //LOW = Pressed, HIGH = Released
#define BTN_LED D7 //LED active low
//ATX
#define PWR_BTN D6
#define RST_BTN D5
#define HDD_LED D2
#define PWR_LED D1

/* WiFi & Web Server Related */
WiFiManager wifiManager;
ESP8266WebServer server(80);

/* Discovery */
#include <ESP8266mDNS.h>
//To prevent collision, the device MAC will be appended to this name
String MDNS_NAME = "espwol";

/* Global Variables */
bool hddLedState = 0;
bool pwrLedState = 0;
bool customBtnPressed = true; 
int val = 0;

/* Function Prototypes */
void handleRoot();
void handleNotFound();
void registerServeEndpoints();
void handleCustomButtonEvents();

void setup() {
  Serial.begin(115200);
  delay(100);
  
  /* Setup WiFi */
  wifiManager.setClass("invert");
  wifiManager.autoConnect("ESP-WakeOnLan");
  Serial.println("[INFO] Connected to WiFi!");

  /* Setup Pins */
  pinMode(PWR_LED, INPUT);
  pinMode(HDD_LED, INPUT);
  pinMode(PWR_BTN, OUTPUT);
  pinMode(RST_BTN, OUTPUT);
  pinMode(BTN_INPUT, INPUT);
  pinMode(BTN_LED, OUTPUT);

  /* Start LittleFS */
  if(!LittleFS.begin()){
    Serial.println("[ERROR] An Error has occurred while mounting LittleFS");
    return;
  }
  Serial.println("[INFO] LittleFS started");

  /* Start mDNS Discovery Service */
  String deviceMAC = WiFi.macAddress();
  deviceMAC.replace(":", "");
  MDNS_NAME = MDNS_NAME + "-" + deviceMAC;
  if (!MDNS.begin(MDNS_NAME)){
      Serial.println("[ERROR] mDNS start failed. Skipping.");
  }else{
      Serial.println("[INFO] mDNS started. Connect to your device using http://" + MDNS_NAME + ".local");
      MDNS.addService("http", "tcp", 80);
  }
  
  /* Bind web listener */
  registerServeEndpoints();
  server.begin();                           
  Serial.println("[INFO] HTTP server started");
}

void loop() {
  server.handleClient();
  handleCustomButtonEvents();
  updateFrontPanelLEDStatus();
  MDNS.update();
}
