#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Arduino_JSON.h>

#define COLORSTEPS 24
#define PIN D2
#define NUMPIXELS 12

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

const char* ssid = "LeWe";
const char* password = "5275274365464843";

ESP8266WebServer server(80);

String lastcommand = "none";


void setup() {

  Serial.begin(115200);
  delay(150);
  Serial.println("ENERGY INDICATOR");

  pinMode(LED_BUILTIN, OUTPUT);  // initialize onboard LED as output
  digitalWrite(LED_BUILTIN, HIGH);  // on D1 mini LED_BUILTIN = HIGH means off

  pixels.begin(); // initialize NeoPixel library.

  Serial.println("Connect WiFi");
  WiFi.hostname("EnergyIndicator");
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    digitalWrite(LED_BUILTIN, LOW);
    delay(250);
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected, IP address: ");
  Serial.println(WiFi.localIP());
  WiFi.setAutoReconnect(true);
  WiFi.persistent(true);

  server.on("/", handle_root);
  server.on("/color", handle_color);
  server.on("/rainbow", handle_rainbow);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
  server.handleClient();
}

void handle_root() {
  String message = "ENERGY INDICATOR\n[";
  message += pixels.getPixelColor(0);

  for (int i = 1; i < NUMPIXELS; i++) {
    message += ", ";
    message += pixels.getPixelColor(i);
  }
  message += "]\n \n";
  
  message += "Last command: ";
  message += lastcommand;
  
  server.send(200, "text/plain", message);
}

void handle_color() {
  if (server.method() == HTTP_GET and server.hasArg("rgb") and server.arg("rgb").length() == 6) {
    int r = hexToDec(server.arg("rgb").substring(0,2));
    int g = hexToDec(server.arg("rgb").substring(2,4));
    int b = hexToDec(server.arg("rgb").substring(4));
    
    Serial.println(server.arg("rgb"));
    Serial.println(r);
    Serial.println(g);
    Serial.println(b);
    
    pixels.fill(pixels.Color(r,g,b), 0, 0);
    pixels.show();

    server.send(200, "text/plain", "Done");
  }
  else if (server.method() == HTTP_POST and server.hasArg("plain")) {
    
    Serial.println(server.arg("plain"));
    JSONVar json = JSON.parse(server.arg("plain"));
    
    pixels.fill(pixels.Color(json["r"],json["g"],json["b"]), 0, 0);
    pixels.show();

    server.send(202, "text/plain", "Done");
  }
 }

void handle_rainbow() {
  pixels.rainbow(0);
  pixels.setBrightness(80);
  pixels.show();
  server.send(200, "text/plain", "Rainbow");
}


void handle_NotFound(){
  server.send(404, "text/plain", "Energy Indicator: Page not found");
}

// https://github.com/benrugg/Arduino-Hex-Decimal-Conversion/blob/master/hex_dec.ino
unsigned int hexToDec(String hexString) {
  
  unsigned int decValue = 0;
  int nextInt;
  
  for (int i = 0; i < hexString.length(); i++) {
    
    nextInt = int(hexString.charAt(i));
    if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
    if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
    if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
    nextInt = constrain(nextInt, 0, 15);
    
    decValue = (decValue * 16) + nextInt;
  }
  
  return decValue;
}
