#include <ESP8266WiFi.h>

#include <ESP8266Ping.h>

#include <ESP8266HTTPClient.h>

#include <WiFiUDP.h>

#include <ESP8266WebServer.h>

const char * ssid = ""; //ganti nama hotspot
const char * pass = ""; //ganti password

//IPAddress localIP(192, 168, 1, 11);       // The desired IP address for the NodeMCU
//IPAddress gateway(192, 168, 1, 1);       // IP address of the gateway/router
//IPAddress subnet(255, 255, 255, 0);      // Subnet mask
//IPAddress dns(8, 8, 8, 8);               // DNS server address

WiFiClient client;

ESP8266WebServer server(80);

// 84:F3:EB:CC:03:EF default MAC
// uint8_t newMACAddress[] = {0x84, 0xF3, 0xEB, 0xCC, 0x03, 0xEF};
// uint8_t newMACAddress[] = {0x50, 0xD2, 0xF5, 0x2F, 0x21, 0x69}; // MAC router
// uint8_t newMACAddress[] = {0x04, 0xe5, 0x98, 0x32, 0xD0, 0x1E}; // MAC Android
// uint8_t newMACAddress[] = {0x34, 0x13, 0xE8, 0xC6, 0x4C, 0x42}; // MAC Komputer

//04:E5:98:32:D0:1E

uint8_t newMACAddress[] = {
  0x34,
  0x13,
  0xE8,
  0xC6,
  0x4C,
  0x42
}; // MAC router (uji collision 1)

// ping ec2.me-south-1.amazonaws.com 99.82.132.91

void do_ping(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  IPAddress remoteIP(a, b, c, d); // Target

  Serial.print("Pinging ");
  Serial.println(remoteIP);

  int pingTime = Ping.ping(remoteIP);
  pingTime = Ping.averageTime();

  if (pingTime > 0) {
    Serial.print("Ping successful! Latency: ");
    Serial.print(pingTime);
    Serial.println(" ms");
  } else {
    Serial.println("Ping failed!");
  }
}

void do_curl(const char * url) {
  HTTPClient http;

  Serial.print("HTTP GET request to: ");
  Serial.println(url);

  http.begin(client, url); // Specify the URL

  int httpCode = http.GET(); // Perform the GET request

  if (httpCode > 0) { // Check for a successful request
    Serial.printf("HTTP GET request successful. Response code: %d\n", httpCode);

    String payload = http.getString(); // Get the response payload (HTML content)

    Serial.println("Response (first 10 characters):");
    Serial.println(payload.substring(0, 10));
  } else {
    Serial.printf("HTTP GET request failed. Error code: %d\n", httpCode);
  }

  http.end(); // Close the connection
}

void traceroute(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  IPAddress destinationIP(a, b, c, d); // Target
  Serial.println("Traceroute:");
  int udpPort = 33434;

  const int maxHops = 30; // Maximum number of hops to attempt
  for (int ttl = 1; ttl <= maxHops; ttl++) {
    WiFiUDP udp;
    IPAddress hopIP = udp.remoteIP();
    udp.beginPacketMulticast(destinationIP, udpPort, WiFi.localIP(), ttl);
    udp.write("Traceroute");
    udp.endPacket();

    Serial.print("Hop ");
    Serial.print(ttl);
    Serial.print(": ");

    int packetSize = udp.parsePacket();
    if (packetSize) {
      Serial.print(hopIP);
    } else {
      Serial.print("*");
    }

    Serial.println();

    // Stop tracing if the destination is reached
    if (hopIP == destinationIP) {
      break;
    }
  }
}

// run HTTP server
void http_server() {
  server.send(200, "text/plain", "Hello World!");
}

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.print(" Connect to : ");
  Serial.println(ssid);
  WiFi.begin(ssid, pass);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print("….");
  }
  Serial.print("\n");
  Serial.print("IP address : ");
  Serial.print(WiFi.localIP());
  Serial.print("\n");
  Serial.print("Connect to : ");
  Serial.println(ssid);
  Serial.print("\n");
  Serial.println(WiFi.macAddress());
  wifi_set_macaddr(STATION_IF, & newMACAddress[0]);
  Serial.print("\n");
  Serial.println(WiFi.macAddress());

  server.on("/", http_server);
  server.begin();

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

}

void loop() {

    // Uji HTTP server
    server.handleClient();

    /*
    // Uji ping dan HTTP GET
    do_ping(192,168,1,11);
    do_ping(192,168,1,1);
    do_ping(192,168,1,74);
    do_ping(192,168,1,99);
    do_curl("http://192.168.1.11"); // Alamat NodeMCU
    do_curl("http://192.168.1.1"); // Alamat router
    do_curl("http://192.168.1.74:1111"); // Alamat Android
    do_curl("http://192.168.1.99"); // Alamat komputer
    // traceroute(192,168,1,1);
    // traceroute(192,168,1,99);
    delay(1000); 

    */
}