#include <LiquidCrystal_PCF8574.h>
#include <WiFi.h>

LiquidCrystal_PCF8574 lcd(0x27); // set the LCD address to 0x27 for a 16 chars and 2 line display

//Esta aplicación crea un nuevo punto de acceso WiFi.
//Modificar las variables ssid y password y conectarse desde un móvil o PC utilizando estos parámetros.
const char* ssid = "ESP32";
const char* password = "123456789";

String request;
unsigned long currentTime = millis();
unsigned long previousTime = 0; 
const long timeoutTime = 2000;

WiFiServer server(80);

#define I0 35
#define I1 32
#define I2 33
#define I3 25
#define I4 26
#define I5 27
#define I6 14

#define Q0 13
#define Q1 12
#define Q2 15
#define Q3 2
#define Q4 4
#define Q5 16
#define Q6 17

#define estado_I0 digitalRead(I0)
#define estado_I1 digitalRead(I1)
#define estado_I2 digitalRead(I2)
#define estado_I3 digitalRead(I3)
#define estado_I4 digitalRead(I4)
#define estado_I5 digitalRead(I5)
#define estado_I6 digitalRead(I6)

boolean estado_Q0 = LOW;
boolean estado_Q1 = LOW;
boolean estado_Q2 = LOW;
boolean estado_Q3 = LOW;
boolean estado_Q4 = LOW;
boolean estado_Q5 = LOW;
boolean estado_Q6 = LOW;

byte alto[] = {
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B11111,
  B00000,
};

byte bajo[] = {
  B11111,
  B10001,
  B10001,
  B10001,
  B10001,
  B10001,
  B11111,
  B00000,
};

void estados() { 
  lcd.setCursor(0,0);
  lcd.print("IP: ");
  lcd.print(WiFi.softAPIP());
  lcd.setCursor(0,1);
  lcd.print("I: ");
  lcd.write(digitalRead(I0));
  lcd.print(" ");
  lcd.write(digitalRead(I1));
  lcd.print(" ");
  lcd.write(digitalRead(I2));
  lcd.print(" ");
  lcd.write(digitalRead(I3));
  lcd.print(" ");
  lcd.write(digitalRead(I4));
  lcd.print(" ");
  lcd.write(digitalRead(I5));
  lcd.print(" ");
  lcd.write(digitalRead(I6));
  lcd.setCursor(0,2);
  lcd.print("   0 1 2 3 4 5 6");
  lcd.setCursor(0,3);
  lcd.print("Q: ");
  lcd.write(digitalRead(Q0));
  lcd.print(" ");
  lcd.write(digitalRead(Q1));
  lcd.print(" ");
  lcd.write(digitalRead(Q2)); 
  lcd.print(" ");
  lcd.write(digitalRead(Q3));
  lcd.print(" ");
  lcd.write(digitalRead(Q4));
  lcd.print(" ");
  lcd.write(digitalRead(Q5));
  lcd.print(" ");
  lcd.write(digitalRead(Q6));
}

void setup() {
  // put your setup code here, to run once:
  pinMode(I0, INPUT);
  pinMode(I1, INPUT);
  pinMode(I2, INPUT);
  pinMode(I3, INPUT);
  pinMode(I4, INPUT);
  pinMode(I5, INPUT);
  pinMode(I6, INPUT);
  pinMode(Q0, OUTPUT);
  pinMode(Q1, OUTPUT);
  pinMode(Q2, OUTPUT);
  pinMode(Q3, OUTPUT);
  pinMode(Q4, OUTPUT);
  pinMode(Q5, OUTPUT);
  pinMode(Q6, OUTPUT);

  lcd.begin(20, 4);
  lcd.createChar(0, bajo);
  lcd.createChar(1, alto);
  delay(200);
  lcd.setBacklight(255);

  WiFi.softAP(ssid, password);

  server.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  WiFiClient client = server.available();   // Listen for incoming clients

  digitalWrite(Q0, estado_Q0);
  digitalWrite(Q1, estado_Q1);
  digitalWrite(Q2, estado_Q2);
  digitalWrite(Q3, estado_Q3);
  digitalWrite(Q4, estado_Q4);
  digitalWrite(Q5, estado_Q5);
  digitalWrite(Q6, estado_Q6);

  estados();

  if (client)                               // If a new client connects,
  {
    currentTime = millis();
    previousTime = currentTime;
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected() && currentTime - previousTime <= timeoutTime)   // loop while the client's connected
    {
      currentTime = millis();
      if (client.available())               // if there's bytes to read from the client,
      {
        char c = client.read();             // read a byte, then
        request += c;
        if (c == '\n')                      // if the byte is a newline character
        {
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0)
          {
            if (request.indexOf("/Q0_on") != -1)
              estado_Q0 = HIGH;
            if (request.indexOf("/Q0_off") != -1)
              estado_Q0 = LOW;

            if (request.indexOf("/Q1_on") != -1)
              estado_Q1 = HIGH;
            if (request.indexOf("/Q1_off") != -1)
              estado_Q1 = LOW;

            if (request.indexOf("/Q2_on") != -1)
              estado_Q2 = HIGH;
            if (request.indexOf("/Q2_off") != -1)
              estado_Q2 = LOW;

            if (request.indexOf("/Q3_on") != -1)
              estado_Q3 = HIGH;
            if (request.indexOf("/Q3_off") != -1)
              estado_Q3 = LOW;

            if (request.indexOf("/Q4_on") != -1)
              estado_Q4 = HIGH;
            if (request.indexOf("/Q4_off") != -1)
              estado_Q4 = LOW;

            if (request.indexOf("/Q5_on") != -1)
              estado_Q5 = HIGH;
            if (request.indexOf("/Q5_off") != -1)
              estado_Q5 = LOW;

            if (request.indexOf("/Q6_on") != -1)
              estado_Q6 = HIGH;
            if (request.indexOf("/Q6_off") != -1)
              estado_Q6 = LOW;

            // HTTP Response in the form of HTML Web Page
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // Display the HTML web page
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println("<head>");
            client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");

            // CSS Styling for Buttons and Web Page
            client.println("<style>");
            client.println("html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println("body {margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}");
            client.println(".button {display: inline-table;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 20px;margin: 0px auto 35px;cursor: pointer;border-radius: 20px;}");
            client.println(".button-on {background-color: #1abc9c;}");
            client.println(".button-on:active {background-color: #16a085;}");
            client.println(".button-off {background-color: #34495e;}");
            client.println(".button-off:active {background-color: #2c3e50;}");
            client.println("</style>");
            client.println("</head>");

            // The main body of the Web Page
            client.println("<body>");
            client.println("<h1>ESP8266 Web Server</h1>\n");
            client.println("<h3>Using Access Point (AP) Mode</h3>\n");

            if (estado_Q0)
              client.println("<a class=\"button button-on\" href=\"/Q0_off\">Q0: ON</a>");
            else
              client.println("<a class=\"button button-off\" href=\"/Q0_on\">Q0: OFF</a>");

            if (estado_Q1)
              client.println("<a class=\"button button-on\" href=\"/Q1_off\">Q1: ON</a>");
            else
              client.println("<a class=\"button button-off\" href=\"/Q1_on\">Q1: OFF</a>");

            if (estado_Q2)
              client.println("<a class=\"button button-on\" href=\"/Q2_off\">Q2: ON</a>");
            else
              client.println("<a class=\"button button-off\" href=\"/Q2_on\">Q2: OFF</a>");

            if (estado_Q3)
              client.println("<a class=\"button button-on\" href=\"/Q3_off\">Q3: ON</a>");
            else
              client.println("<a class=\"button button-off\" href=\"/Q3_on\">Q3: OFF</a>");

            if (estado_Q4)
              client.println("<a class=\"button button-on\" href=\"/Q4_off\">Q4: ON</a>");
            else
              client.println("<a class=\"button button-off\" href=\"/Q4_on\">Q4: OFF</a>");

            if (estado_Q5)
              client.println("<a class=\"button button-on\" href=\"/Q5_off\">Q5: ON</a>");
            else
              client.println("<a class=\"button button-off\" href=\"/Q5_on\">Q5: OFF</a>");

            if (estado_Q6)
              client.println("<a class=\"button button-on\" href=\"/Q6_off\">Q6: ON</a>");
            else
              client.println("<a class=\"button button-off\" href=\"/Q6_on\">Q6: OFF</a>");

            client.println("</body>");
            client.println("</html>");
            client.println("");
            break;
          }
          else                              // if you got a newline, then clear currentLine
            currentLine = "";
        }
        else if (c != '\r')                 // if you got anything else but a carriage return character,
          currentLine += c;                 // add it to the end of the currentLine
      }
    }
    request = "";
    client.stop();
  }
}