#include <Arduino.h>
#include <HTTPClient.h>
#include <WiFi.h>
#include <WebServer.h>
#include <time.h>
#include <sys/time.h>
#include <Arduino_JSON.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include <LittleFS.h>
#include <Servo.h>
#include <PicoOTA.h>
#include <uri/UriRegex.h>

LiquidCrystal_I2C lcd(0x27,20,4); 

int led = LED_BUILTIN;

const char* ssid = "jawn";
const char* password = "92ae2dd1414dff025e16775f1d";

const char* host = "192.168.1.3";
const uint16_t port = 3000;

WiFiMulti multi;
WebServer server(3000);
String homebase;
String homebaseIP;
String browser_tab_id;
int homebaseOnline = millis();
int lastPing = millis();
String wifiState;
String authorization;
String before_me;
int time_defined = 0;
long offset;
int input_working = 0;
JSONVar config;

Servo myservo;
WiFiClientSecure *connexion = new WiFiClientSecure;
HTTPClient https;
JSONVar coreJobs;
File rawFile;
int rebooting = 0;

void setup1() {
  Serial.begin(115200);
  Serial.println("Core 1 started");
}

void setup() {
  Serial.begin(115200);
  pinMode(led, OUTPUT);
  digitalWrite(led,HIGH);
  delay(200);
  LittleFS.begin();
  pinMode(0, OUTPUT);

  digitalWrite(0, HIGH);

  File f = LittleFS.open("config.txt", "r");
  String jconfig = f.readString();
  Serial.println(jconfig);
  config = JSON.parse(jconfig);
  config_init();
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  multi.addAP(ssid, password);
  if (multi.run() == WL_CONNECTED) {
    wifiState = "connected";
    coreJobs["connect"]["type"] = "led";
    coreJobs["connect"]["interval"] = "100";
    coreJobs["connect"]["duration"] = "500";
    if (authorization && homebaseIP) {
      String req = "https://" + homebaseIP + "/watch/time?";
      String timeRequest = https_request(req);
      String jobTime = String(millis());
      coreJobs[jobTime]["type"] = "https";
      coreJobs[jobTime]["url"] = req;
      coreJobs[jobTime]["response"] = "time";
    }
  }
  else {
    wifiState = "disconnected";
  }
  server.begin();
  

  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.on("/device_query", []() {
    config["chip_id"] = rp2040.getChipID();
    config["uptime"] = millis();
    config["purpose"] = "microcontroller";
    config["model"] = "Raspberry Pi Pico 2W";
    config["pins"] = "28";

    String gs = JSON.stringify(config);
    server.send(200, "text/plain", gs);
    config_writer();
  });

  server.on("/jobs", []() {
    String auth = server.arg("authorization");
   // if (auth == authorization) {
      String jobs = JSON.stringify(config["jobs"]);
      Serial.println(jobs);
      server.send(200, "text/plain", jobs);
   // }

  });

  server.on("/now_me", []() {
    homebaseChecked();
    homebaseIP = server.arg("homebase");
    homebase = server.arg("ip");
    config["authorization"] = server.arg("authorization");
    authorization = server.arg("authorization");
    config["name"] = server.arg("name");
    Serial.println(server.arg("name"));
    browser_tab_id = server.arg("browser_tab_id");
    Serial.println(server.arg("authorization"));
    Serial.println(config["name"]);
    long timestamp = server.arg("timestamp").toInt();
    config["timestamp"] = server.arg("timestamp");
    config["offset"] = server.arg("offset");
    offset = server.arg("offset").toDouble();
    config["homebase"] = server.arg("ip");
    config["homebaseIP"] = server.arg("homebase");
    Serial.println("Homebase: " + homebase);
    Serial.println("homebase ip:" + homebaseIP);
    struct timeval tv;
    tv.tv_sec = (timestamp + offset);
    settimeofday(&tv,nullptr);
    time_defined = 1;
    // Serial.println("Called President at " + homebaseIP);
    server.send(200, "text/plain", "homebase ip is now " + homebaseIP);
    config_writer();
    call_the_president();
  });
  server.on("/delete_job", []() {
    homebaseChecked();
    String appt_uuid = server.arg("appt_uuid");
    Serial.println("Querying " + appt_uuid);
    JSONVar jobKeys = config["jobs"].keys();
    int jlLength = jobKeys.length();
    for (int i = 0; i < jlLength; i++) {
      
      String app_uuid = config["jobs"][jobKeys[i]]["appt_uuid"];
      Serial.println("Testing " + app_uuid);
      if (appt_uuid == app_uuid) {
        Serial.println("deleting " + appt_uuid);
        String uuid = config["jobs"][jobKeys[i]]["uuid"];    
        config["jobs"][uuid] = undefined;
        jlLength--;
        Serial.println("Deleted " + uuid);
      }
    }
    config_writer();
    server.send(200, "text/plain", "ok");
  });
  server.on("/led", []() {
    homebaseChecked();
    String component = server.arg("component");
    String spin = server.arg("pin");
    int pin = server.arg("pin").toInt();
    String state = server.arg("state");
    String timestamp = server.arg("timestamp");
    String uuid = server.arg("uuid");
    String when = server.arg("when");
    String appt_uuid = server.arg("appt_uuid");
    if (when == "now") {
      state = led_toggle(pin,state);
    }
    else {
      push_job(component,pin,state,timestamp,uuid, appt_uuid);
    }
    JSONVar status;
    status["pin"] = pin;
    status["state"] = state;

    String jstatus = JSON.stringify(status);
    server.send(200, "text/plain", jstatus);
    config_writer();
    
  
  });
  server.on("/relay", []() {
    homebaseChecked();
    String component = server.arg("component");
    String spin = server.arg("pin");
    int pin = server.arg("pin").toInt();
    String state = server.arg("state");
    String timestamp = server.arg("timestamp");
    String when = server.arg("when");
    String uuid = server.arg("uuid");
    String appt_uuid = server.arg("appt_uuid");
    if (when == "now") {
      state = relay_toggle(pin,state);
    }
    else {
      push_job(component,pin,state,timestamp,uuid, appt_uuid);
    }
    JSONVar status;
    status["pin"] = pin;
    status["state"] = state;

    String jstatus = JSON.stringify(status);
    server.send(200, "text/plain", jstatus);
  });
  server.on("/servo", []() {
    homebaseChecked();
    String component = server.arg("component");
    String spin = server.arg("pin");
    int pin = server.arg("pin").toInt();
    String state = String(server.arg("state"));
    String timestamp = server.arg("timestamp");
    String when = server.arg("when");
    String uuid = server.arg("uuid");
    String appt_uuid = server.arg("appt_uuid");
    Serial.println(component + " " + spin + " " + state);
    if (when == "now") {
      state = servo_toggle(pin,state);
    }
    else {
      push_job(component,pin,state,timestamp,uuid, appt_uuid);
    }
    JSONVar status;
    status["pin"] = pin;
    status["state"] = state;

    String jstatus = JSON.stringify(status);
    server.send(200, "text/plain", jstatus);    
  });
  server.on("/wifi_update", []() {
    homebaseChecked();
    String req = "https://" + homebaseIP + "/teletype/wifi_update?";
    String wifi_update = https_request(req);
    
    JSONVar info = JSON.parse(wifi_update);
    if (ssid != (const char *)info["ssid"] || password != (const char* )info["password"]) {
      ssid = (const char *)info["ssid"];
      password = (const char * )info["password"];
      config["ssid"] = ssid;
      config["password"] = password;
      multi.clearAPList();
      server.stop();
      server.close();
      delay(400);
      multi.addAP(ssid, password);
      if (multi.run() != WL_CONNECTED) {
        Serial.println("Unable to connect to network, rebooting in 10 seconds...");
        delay(10000);
        rp2040.reboot();
      }
      server.begin();

      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
    }
  });
  
  server.on(UriRegex("/upload/(.*)"), HTTP_POST, handleCreate, handleCreateProcess);
 
  // for i2c variants, this must be called first.
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  lcd.setBacklight(1);
  // Print a message to the LCD.
  lcd.print(config["name"]);

}


void handleCreate() {
  server.send(200, "text/plain", "");
}
int lastOTAMillis = millis();
int lastOTASendMillis = millis();
void ledFlasher(int interval, int duration) {
  pinMode(led, OUTPUT);
  int end_time = (millis() + duration);
  while (millis() < end_time) {
    if (digitalRead(led) == 1) {
      digitalWrite(led, LOW);
    }
    else {
      digitalWrite(led, HIGH);
    }
    delay(interval);
  }
  digitalWrite(led, HIGH);
}


void handleCreateProcess() {
  pinMode(led, OUTPUT);
  int brightness = 255;
  String path = "/" + server.pathArg(0);
  HTTPRaw& raw = server.raw();
  
  if (raw.status == RAW_START) {
    if (LittleFS.exists((char *)path.c_str())) {
      LittleFS.remove((char *)path.c_str());
    }
    rawFile = LittleFS.open(path.c_str(), "w");
    
  } else if (raw.status == RAW_WRITE) {
    if (rawFile) {
      rawFile.write(raw.buf, raw.currentSize);
    }
    if (millis() > (lastOTAMillis + 20)) {
      lastOTAMillis = millis();
      if (digitalRead(led) == 1) {
        digitalWrite(led, LOW);
      }
      else {
        digitalWrite(led, HIGH);
      }
    }
    if (millis() > (lastOTASendMillis + 3000)) {
      lastOTASendMillis = millis();
      String current_size = String(raw.totalSize);
      String jobTime = String(millis());
      coreJobs[jobTime]["type"] = "https";
      coreJobs[jobTime]["url"] = "https://" + homebaseIP +
        "/watch/ota_status?current_size=" + current_size +
        "&status=uploading";
      
    }
  } else if (raw.status == RAW_END) {
    if (rawFile) {
      rawFile.close();
    }
    String current_size = String(raw.totalSize);

    String jobTime = String(millis());
    coreJobs[jobTime]["type"] = "https";
    coreJobs[jobTime]["url"] = "https://" + homebaseIP +
      "/watch/ota_status?current_size=" + current_size +
      "&status=updating";

    picoOTA.begin();
    picoOTA.addFile(path.c_str());
    picoOTA.commit();
    LittleFS.end();
    LittleFS.remove((char *)path.c_str());
    
    String https = https_request(
      "https://" + homebaseIP +
      "/watch/ota_status?current_size=" + current_size +
      "&status=complete"
    );
    delay(1000);
    rebooting = 1;
  }
}
void loop() {
  server.handleClient();
  read_time();
  input_scanner();
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial.write(inByte);
  }

  if (BOOTSEL) {
    File f = LittleFS.open("config.txt", "w");
    f.print("");
    Serial.println(rp2040.getChipID());
    rp2040.reboot();
  }

  delay(10);
}

void loop1() {
  if (millis() > (lastPing + 60000)) {
    homebasePing();
  }
  if (rebooting == 1) {
    rp2040.reboot();
  }
  handle_jobs();
//  delay(10);
}

void homebasePing() {
  if (wifiState == "connected") {
    homebaseOnline = 1;
    String https = https_request(
      "https://" + homebaseIP +
      "/watch/alive?millis=" + millis()
    );
    Serial.println(https);
    if (https == "alive") {
      homebaseChecked();
    }
    else {
      Serial.println("no ping");
      homebaseOnline = 0;
    }
  }
  else {
    if (multi.run() == WL_CONNECTED) {
      wifiState = "connected";
      homebasePing();
    }
    else {
      wifiState = "disconnected";
    }
  }
  lastPing = millis();
}

void homebaseChecked() {
  homebaseOnline = millis();
  lastPing = millis();
}

void input_scanner() {
  if (input_working == 1) {
    return;
  }
  input_working = 1;
  JSONVar buttonKeys = config["button"].keys();
  for (int i = 0; i < buttonKeys.length(); i++) {
    String spin = buttonKeys[i];
    int pin = spin.toInt();
    int buttonState = digitalRead(pin);
    String lastPress = config["button"][buttonKeys[i]]["lastPress"];
    String pressed = config["button"][buttonKeys[i]]["pressed"];

    long lp = lastPress.toInt();
    if (buttonState == 0 && pressed == "yes") {
      config["button"][buttonKeys[i]]["pressed"] = "no";
      config_writer();
    }
    if (buttonState == 1 && (millis() > lp + 10 && pressed != "yes")) {
      config["button"][buttonKeys[i]]["lastPress"] = String(millis());
      config["button"][buttonKeys[i]]["pressed"] = "yes";
      String toggle = buttonKeys[buttonKeys[i]]["toggle"];

      String name = String(config["button"][buttonKeys[i]]["name"]);
      String jij = config["internal_jobs"];
      Serial.println(jij);
      Serial.println(config["button"][buttonKeys[i]]["name"]);
      JSONVar ij = JSON.parse(jij);
      if (ij[name].length() > 0) {
        Serial.println("I have job for this");
        for (int j = 0; j < ij[name].length(); j++) {
          int p = String(ij[name][j]["numero"]).toInt();
          int inv = String(ij[name][j]["inverted"]).toInt();
          String comp = String(ij[name][j]["component"]);
          String tog = String(config[comp][String(ij[name][j]["numero"])]);
          Serial.println(comp + " " + String(ij[name][j]["numero"]) + " " + tog);
          String jState = "off";
          toggle = "0";
          if (inv == 1) {
            if (tog == "off") {
              jState = "on";
              toggle = "0";
            }
            else {
              toggle = "1";
            }
          }
          else {
            if (tog != "on") {
              jState = "on";
              toggle = "1";
            }
            else {
              toggle = "0";
            }
          }
          Serial.println(comp + " " + String(ij[name][j]["numero"]) + " " + jState + " after");
          if (comp == "relay") {
            relay_toggle(p, jState);
          }
          if (comp == "led") {
            led_toggle(p, jState);
          }
        }

      }
      config_writer();

      String jobTime = String(millis());
      coreJobs[jobTime]["type"] = "https";
      coreJobs[jobTime]["url"] = "https://" + homebaseIP +
        "/watch/button?room=1&button=" + spin + "&toggle=" + toggle;
      coreJobs[jobTime]["response"] = "button";

      //JSONVar returner = JSON.parse(https);
      //config["button"][buttonKeys[i]]["toggle"] = returner["toggle"];
      config_writer();
    }
  }
  JSONVar switchKeys = config["switch"].keys();
  for (int i = 0; i < switchKeys.length(); i++) {
    String spin = switchKeys[i];
    int pin = spin.toInt();
    int switchState = digitalRead(pin);
    String state;
    if (switchState == 1) {
      state = "on";
    }
    else {
      state = "off";
    }
    String lastChange = config["switch"][switchKeys[i]]["lastChange"];
    String lastState = String(config["switch"][switchKeys[i]]["state"]);
    long lc = lastChange.toInt();
    if (state != lastState) {
      config["switch"][switchKeys[i]]["state"] = state;
      config["switch"][switchKeys[i]]["lastChange"] = String(millis());

      String name = String(config["switch"][switchKeys[i]]["name"]);
      String jij = config["internal_jobs"];
      Serial.println(jij);
      Serial.println(config["switch"][switchKeys[i]]["name"]);
      JSONVar ij = JSON.parse(jij);
      if (ij[name].length() > 0) {
        Serial.println("I have job for this");
        for (int j = 0; j < ij[name].length(); j++) {
          int p = String(ij[name][j]["numero"]).toInt();
          int inv = String(ij[name][j]["inverted"]).toInt();
          String jState = state;
          if (inv == 1) {
            if (state == "on") {
              jState = "off";
            }
            else {
              jState = "on";
            }
          }
          if (String(ij[name][j]["component"]) == "relay") {
            relay_toggle(p, jState);
          }
          if (String(ij[name][j]["component"]) == "led") {
            led_toggle(p, jState);
          }
        }
      }

      String jobTime = String(millis());
      coreJobs[jobTime]["type"] = "https";
      coreJobs[jobTime]["url"] = "https://" + homebaseIP +
        "/watch/switch?room=1&switch=" + spin + "&state=" + state;
      coreJobs[jobTime]["response"] = "switch";
      config["switch"][switchKeys[i]]["lastSend"] = String(millis());
    //  config["button"][buttonKeys[i]]["state"] = returner["toggle"];
      config_writer();
    }
  }
  JSONVar potKeys = config["pot"].keys();
  for (int i = 0; i < potKeys.length(); i++) {
    String spin = potKeys[i];
    int pin = spin.toInt();
    int potState = analogRead(pin);
   // Serial.println(potState);
    String bs = String(potState);
    int lbs = String(config["pot"][spin]["lastValue"]).toInt();
    String changed = String(config["pot"][spin]["changed"]);
    String ls = (const char *)config["pot"][spin]["lastSend"];
    int lastSend = ls.toInt();
    if (potState != lbs || changed == "yes") {
      int min = lbs - 12;
      int max = lbs + 12;
      String lm = (const char *)config["pot"][spin]["lastMove"];
      int lastMove = lm.toInt();
      lastMove = lastMove + 300;

      if (potState < min || potState > max) {
        config["pot"][spin]["lastMove"] = String(millis());
        lastMove = millis();
        lastMove = lastMove;// + 300;
        Serial.println(bs);

        String name = String(config["pot"][potKeys[i]]["name"]);
        String jij = config["internal_jobs"];
        Serial.println(config["pot"][potKeys[i]]["name"]);
        JSONVar ij = JSON.parse(jij);
        if (ij[name].length() > 0) {
          config["pot"][spin]["lastValue"] = bs;          

          for (int j = 0; j < ij[name].length(); j++) {
            int p = String(ij[name][j]["numero"]).toInt();
            int inv = String(ij[name][j]["inverted"]).toInt();
            String tp = String(ij[name][j]["threshold_percentage"]);
            double thresh = tp.toDouble();
            
            
            Serial.println(potState);

            thresh = ( thresh / 100 ) * 1024;
            Serial.println(thresh);
            String jState = "off";
            if (inv == 1) {
              if (potState <= thresh) {
                jState = "on";
              }
            }
            else {
              if (potState >= thresh) {
                jState = "on";
              }
            }
            if (String(ij[name][j]["component"]) == "relay") {
              relay_toggle(p, jState);
            }
            if (String(ij[name][j]["component"]) == "led") {
              led_toggle(p, jState);
            }
          }
          
          config["pot"][spin]["changed"] = "yes";

          config_writer();
        }

      }


      if (millis() < lastSend) {
        config["pot"][spin]["lastSend"] = String(millis());
      }
      lastSend = lastSend + 500;
      changed = String(config["pot"][spin]["changed"]);
      if (lastSend < millis() && lastMove < millis() && changed == "yes") {
        config["pot"][spin]["lastSend"] = String(millis());
          
        potState = analogRead(pin);
          // Serial.println(potState);
        bs = String(potState);
        config["pot"][spin]["lastValue"] = bs;
        config["pot"][spin]["changed"] = "no";
        
        config_writer();
        String jobTime = String(millis());
        coreJobs[jobTime]["type"] = "https";
        coreJobs[jobTime]["url"] = "https://" + homebaseIP +
          "/watch/measure?room=1&button=" + spin + "&measure=" + bs +
          "&component=pot&min=0&max=1024";
        coreJobs[jobTime]["response"] = "pot";

      }
    }
  }
  input_working = 0;
}

String led_toggle(int pin, String state) {

  pinMode(pin, OUTPUT);

  if (state == "on") {
    digitalWrite(pin, HIGH);
  }
  else {
    digitalWrite(pin, LOW);
  }
  String spin = String(pin);
  config["led"][spin] = state;
  config_writer();
  return state;
}

String relay_toggle(int pin, String state) {

  pinMode(pin, OUTPUT);

  if (state == "on") {
    digitalWrite(pin, HIGH);
  }
  else {
    digitalWrite(pin, LOW);
  }
  String spin = String(pin);
  config["relay"][spin] = state;
  config_writer();
  return state;
}

String servo_toggle(int pin, String state) {
  int stat = state.toInt();

  int val = (stat / 100);
  Serial.println(val);
  val = val * 180;
  String spin = String(pin);
  Serial.println(val);
  Serial.println(stat);
  
  if (!myservo.attached()) {
    myservo.attach(pin);
  }
  myservo.write(stat);
  String vale = String(val);
  config["servo"][spin] = vale;
  config_writer();
  return vale;
}
void push_job(String component,int pin, String state, String timestamp, String uuid, String appt_uuid) {
  String spin = String(pin);
  Serial.println("pushing job " + uuid + " " + timestamp);
  config["jobs"][uuid]["pin"] = spin;
  config["jobs"][uuid]["timestamp"] = timestamp;
  config["jobs"][uuid]["component"] = component;
  config["jobs"][uuid]["state"] = state;
  config["jobs"][uuid]["uuid"] = uuid;
  config["jobs"][uuid]["appt_uuid"] = appt_uuid;
}

void handle_jobs() {
  if (time_defined == 1 && config["jobs"].keys().length() > 0) {
    struct timeval tv;
    time_t now;
    time(&now);
    gettimeofday(&tv,NULL);
    int64_t timestamp = ((int64_t)tv.tv_sec * 1000LL + (int64_t)tv.tv_usec / 1000LL) - (offset * 1000);

    JSONVar jobKeys = config["jobs"].keys();
    for (int i = 0; i < jobKeys.length(); i++) {
      String times = String(config["jobs"][jobKeys[i]]["timestamp"]);
      int64_t ts = times.toDouble();

      if (timestamp >= ts) {
        Serial.print(jobKeys[i]);
        Serial.println(ts);
        String spin = config["jobs"][jobKeys[i]]["pin"];
        String component = config["jobs"][jobKeys[i]]["component"];
        String state = config["jobs"][jobKeys[i]]["state"];
        String uuid = config["jobs"][jobKeys[i]]["uuid"];

        int pin = spin.toInt();
        if (component == "relay") {
          state = relay_toggle(pin,state);
        }
        else if (component == "led") {
          state = led_toggle(pin,state);
        }
        else if (component == "servo") {
          state = servo_toggle(pin,state);
        }
        
        config["jobs"][uuid] = undefined;
      }
    }
  }
  JSONVar coreKeys = coreJobs.keys();

  for (int i = 0; i < coreKeys.length(); i++) {
    Serial.println("core job ");
    Serial.println(coreKeys[i]);
    Serial.println(coreJobs[coreKeys[i]]["type"]);
    if (String(coreJobs[coreKeys[i]]["type"]) == "led") {
      int interval = String(coreJobs[coreKeys[i]]["interval"]).toInt();
      int duration = String(coreJobs[coreKeys[i]]["duration"]).toInt();
      ledFlasher(interval,duration);
    }
    else if (String(coreJobs[coreKeys[i]]["type"]) == "https") {
      String url = String(coreJobs[coreKeys[i]]["url"]);
      String response = https_request(url);

      if (String(coreJobs[coreKeys[i]]["response"]) == "button") {
        JSONVar returner = JSON.parse(response);
        config["button"][returner["button"]]["toggle"] = returner["toggle"];
      }
      if (String(coreJobs[coreKeys[i]]["response"]) == "switch") {
        JSONVar returner = JSON.parse(response);
        config["switch"][returner["switch"]]["state"] = returner["state"];
      }
      if (String(coreJobs[coreKeys[i]]["response"]) == "time") {
        JSONVar timers = JSON.parse(response);

        long timestamp = timers["timestamp"];
        timestamp = timestamp - (60 * 9) + 4;
        long offset = timers["offset"];
        struct timeval tv;
        tv.tv_sec = (timestamp + offset);
        settimeofday(&tv,nullptr);
        time_defined = 1;  
      }

    }
    coreJobs[coreKeys[i]] = undefined;
  }
}

uint32_t lastMillis;

void read_time() {
  if (millis() >= (lastMillis + 1000)) { 
    lastMillis = millis();
    time_t now;
    char buffdate[80];
    char bufftime[80];

    time(&now);
    struct tm tmstruct;
    localtime_r(&now,&tmstruct);
    
    strftime(buffdate, 64, "%a %b %d %Y", &tmstruct);
    strftime(bufftime, 64, "%H:%M:%S", &tmstruct);
    
    String timing = (const char *)buffdate;
    lcd.setCursor(0,0);
    lcd.print(timing);
    lcd.setCursor(0,1);
    String timings = (const char *)bufftime;
    lcd.print(timings);
  }
}

void config_writer() {
  config["uptime"] = millis();
  String jconfig = JSON.stringify(config);
  File f = LittleFS.open("config.txt", "w");
  f.print(jconfig);
//  Serial.println(jconfig);
}

void config_init() {
  Serial.println("Config init");
  JSONVar relayKeys = config["relay"].keys();
  for (int i = 0; i < relayKeys.length(); i++) {
    Serial.print(relayKeys[i]);
    Serial.println(config["relay"][relayKeys[i]]);
    String state = config["relay"][relayKeys[i]];
    String spin = relayKeys[i];
    int pin = spin.toInt();
    pinMode(pin, OUTPUT);

    if (state == "on") {  
      digitalWrite(pin, HIGH);
    }
    else {
      digitalWrite(pin,LOW);
    }
  }
  JSONVar ledKeys = config["led"].keys();
  for (int i = 0; i < ledKeys.length(); i++) {
    Serial.print(relayKeys[i]);
    Serial.println(config["led"][ledKeys[i]]);
    String state = config["led"][ledKeys[i]];
    String spin = ledKeys[i];
    int pin = spin.toInt();
    pinMode(pin, OUTPUT);    
    if (state == "on") {
      digitalWrite(pin, HIGH);
    }
    else {
      digitalWrite(pin, LOW);
    }
  }
  JSONVar buttonKeys = config["button"].keys();
  for (int i = 0; i < buttonKeys.length(); i++) {
    Serial.print(buttonKeys[i]);
    Serial.println(config["button"][buttonKeys[i]]);
    String toggle = config["button"][buttonKeys[i]]["toggle"];
    config["button"][buttonKeys[i]]["lastPress"] = String(millis());
    String spin = buttonKeys[i];
    int pin = spin.toInt();
    pinMode(pin, INPUT);    
  }
  JSONVar switchKeys = config["switch"].keys();
  for (int i = 0; i < switchKeys.length(); i++) {
    String state = config["switch"][switchKeys[i]]["state"];
    config["switch"][switchKeys[i]]["lastChange"] = String(millis());
    config["switch"][switchKeys[i]]["lastSend"] = String(millis());
    String spin = switchKeys[i];
    int pin = spin.toInt();

    pinMode(pin, INPUT);
  }
  JSONVar potKeys = config["pot"].keys();
  for (int i = 0; i < potKeys.length(); i++) {
    config["pot"][potKeys[i]["lastMove"]] = String(millis());
    config["pot"][potKeys[i]["lastSend"]] = String(millis());

    String spin = potKeys[i];
    int pin = spin.toInt();
  //  pinMode(pin, INPUT);
  }


  JSONVar servoKeys = config["servo"].keys();
  for (int i = 0; i < servoKeys.length(); i++) {
    Serial.print(servoKeys[i]);
    Serial.println(config["servo"][servoKeys[i]]);
    String state = config["servo"][servoKeys[i]];
    String spin = servoKeys[i];
    int pin = spin.toInt();
    
    myservo.attach(pin);
  }
  authorization = (const char * )config["authorization"];
  homebase = String(config["homebase"]);
  homebaseIP = String(config["homebaseIP"]);
  if (config["ssid"] && config["password"]) {
    ssid = config["ssid"];
    password = config["password"];
  }

/*    

  String tstamp = String(config["timestamp"]);
  long timestamp = tstamp.toInt();
  timestamp = timestamp - (60 * 9) + 4;
  String oset = String(config["offset"]);
  long offset = oset.toInt();
  Serial.print("time setting ");
  Serial.print(tstamp);
  Serial.print(" ");
  Serial.println(timestamp);
  struct timeval tv;
  tv.tv_sec = (timestamp + offset);
  settimeofday(&tv,nullptr);
*/
}

String url_maker(String url) {
  String chip_id = rp2040.getChipID();
  url = url + "&edt=microcontroller&chip_id=" + chip_id + "&authorization=" + authorization;
  return url;
}

String https_request(String url) {
  
  if (homebaseOnline == 0) {
    return "no ping";
  }
  url = url_maker(url);
  Serial.println("In the https request");
  Serial.println(url);
  connexion -> setInsecure();
  Serial.print("homebase online ");
  Serial.println(homebaseOnline);
  if (connexion && homebaseOnline > 0) {
    {
      Serial.println("Starting connexion");
      if (https.begin(*connexion, url)) {
        
        Serial.println("Right after connexion");
        int httpCode = https.GET();
        Serial.println(httpCode);
        if (httpCode > 0) {

          if (httpCode == HTTP_CODE_OK) {
            homebaseOnline = millis();
            String payload = https.getString();
            return payload;
          }
        }
        else {
          Serial.printf("HTTPS FAILED error: %s\n", https.errorToString(httpCode).c_str());
          homebaseOnline = 0;
          return "failure";
        }
        https.end();
      }
    }
  }
  homebaseOnline = 0;
  return "failure";
}

void call_the_president() {
  //  Serial.println("dans presidente");
  //  Serial.println(before_me);
  //  Serial.println("copy");
  JSONVar result;
  Serial.print("bb: " );
  if (homebaseIP != "") {
    String req = "https://" + homebaseIP + "/watch?room=1&browser_tab_id=" + browser_tab_id;
    Serial.println(req);
    String watchRequest = https_request(req);
    Serial.println(watchRequest);
    if (watchRequest != "failure") {
      before_me = watchRequest;
      if (before_me != "No!") {
        JSONVar ctp = JSON.parse(before_me);
        JSONVar ctpKeys = ctp.keys();
        config["button"] = undefined;
        config["pot"] = undefined;
        config["led"] = undefined;
        config["servo"] = undefined;
        config["relay"] = undefined;
        config["switch"] = undefined;
        config["internal_jobs"] = undefined;
        for (int i = 0; i < ctpKeys.length(); i++) {
          String numero = ctp[ctpKeys[i]]["numero"];  
          String component = ctp[ctpKeys[i]]["component"];
          String name = String(ctpKeys[i]);
          int pin = numero.toInt();
          if (component == "button") {
            String toggle = ctp[ctpKeys[i]]["toggle"];
            config["button"][numero]["lastPress"] = String(millis());
            config["button"][numero]["toggle"] = toggle;
            config["button"][numero]["name"] = name;
            pinMode(pin, INPUT);

          }
          else if (component == "pot") {
            config["pot"][numero]["lastMove"] = String(millis());
            config["pot"][numero]["lastSend"] = String(millis());
            config["pot"][numero]["name"] = name;
          //  pinMode(pin, INPUT);
          }
          else if (component == "switch") {
            config["switch"][numero]["lastChange"] = String(millis());
            config["switch"][numero]["lastSend"] = String(millis());
            config["switch"][numero]["name"] = name;
            pinMode(pin, INPUT);
          }
          else if (name == "__specs") {
            String ij = JSON.stringify(ctp[ctpKeys[i]]["internal_jobs"]);
            Serial.println(ij);
            config["internal_jobs"] = ij;
            Serial.println("this is an inside job");
          }
          Serial.println(name);
        }
      }
      config_writer();
      config_init();
      coreJobs["president"]["type"] = "led";
      coreJobs["president"]["interval"] = "50";
      coreJobs["president"]["duration"] = "1000";

    }
  }

  //Serial.println(before_me);
}
