#include <WiFi.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>

#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
#define WIFI_CHANNEL 6

#define pinA 4
#define pinB 16
#define pinC 17
#define pinD 18

#define numberOfButtons 4

int pinArray[numberOfButtons] = {pinA, pinB, pinC, pinD};

const int JSON_SIZE = 5000;
const String API_URL = "https://studybotapi.pythonanywhere.com/getUploadedQuestion";



class APIManager{
  private:
    
    String apiUrl;
    int jsonSize;

    String callAPI() {
      if (WiFi.status() == WL_CONNECTED) {
        HTTPClient http;
        http.begin(this->apiUrl);

        int httpResponseCode = http.GET();

        if (httpResponseCode > 0) {
          String value = http.getString();
          http.end();
          return value;
        }
        else{
          Serial.print("Api failed");
        }
        http.end();
      } else {
        Serial.println("WiFi not connected");
      }
  }

  public:

    APIManager(String apiUrl, int jsonSize){
      this->apiUrl = apiUrl;
      this->jsonSize = jsonSize;
    }

    JsonDocument getJson(){
      DynamicJsonDocument jsonDoc(this->jsonSize);
      String jsonString = this->callAPI();
      DeserializationError error = deserializeJson(jsonDoc, jsonString);
      if (error) {
        Serial.print("JSON deserialization failed: ");
        Serial.println(error.c_str());
      }
      return jsonDoc;
    }
};

class QuestionManager{
  private:
    JsonArray questionsArray;
    size_t currentIndex = 0;

    JsonObject getCurrentQuestion(){
      return questionsArray[currentIndex].as<JsonObject>();
    }
    
  public:

    QuestionManager(JsonArray questionsArray){
      this->questionsArray = questionsArray;
    }

    bool checkIfCorrectAnswer(String chosenAnswer){
      String correctAnswer = this->getCurrentQuestion()["answer"].as<String>();
      return chosenAnswer == correctAnswer;
    }

    JsonObject getChoices(){
      return this->getCurrentQuestion()["choices"].as<JsonObject>();
    }

    String getQuestion(){
      return this->getCurrentQuestion()["question"].as<String>();
    }

    void nextQuestion(){
      if(questionsArray.size() <= 0){
        Serial.println("The question is empty!");
      }
      this->currentIndex++;
      if(this->currentIndex >= questionsArray.size()){
        this->currentIndex = 0;
        Serial.println("Reset!");
      }
    }
};

struct Button {
      int pin;
      String answer;
};

class ButtonManager{
  private:
    Button buttonList[numberOfButtons];

  public:
    ButtonManager(int buttonPins[]){
      for(int index = 0; index < numberOfButtons; index++){
        int buttonPin = buttonPins[index];
        this->buttonList[index].pin = buttonPin;
        pinMode(buttonPin, INPUT);
      }

    }

    void setChoices(String* choices){
      for(int index = 0; index < numberOfButtons; index++){
        this->buttonList[index].answer = choices[index];
      }
    }

    String checkIfPressedButton(){
      for(Button& button : this->buttonList){
        bool pressedButton = digitalRead(button.pin);
        if(pressedButton){
          return button.answer;
        }
      }
      return "";
    }
};

void startWifi(String wifiSSID, String wifiPassword, int wifiChannel){
  WiFi.begin(wifiSSID, wifiPassword, wifiChannel);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println();
  Serial.println("Connected to Wi-Fi");
}

// Initialize Objects Memory
QuestionManager* questionManager;
APIManager apiManager(API_URL, JSON_SIZE);
ButtonManager* buttonManager;
JsonDocument mainQuestionJson;

String *getChoices(){
    JsonObject choicesJson = questionManager->getChoices();
    static String newChoices[numberOfButtons];
    int index = 0;
    for (JsonPair keyValuePair : choicesJson) {
      String currentChoice = keyValuePair.value().as<String>();
      newChoices[index++] = currentChoice;
    }
    return newChoices;
}

void setup() {
  Serial.begin(115200);
  startWifi(WIFI_SSID, WIFI_PASSWORD, WIFI_CHANNEL);
  mainQuestionJson = apiManager.getJson();

  String title = mainQuestionJson["title"].as<String>();
  questionManager = new QuestionManager(mainQuestionJson["questions"].as<JsonArray>());
  buttonManager = new ButtonManager(pinArray);
  String* choices = getChoices();
  buttonManager->setChoices(choices);
  printQuestion(questionManager->getQuestion());
  printChoices(choices);

}

void printChoices(String *choices){
  Serial.println("A: " + choices[0]);
  Serial.println("B: " + choices[1]);
  Serial.println("C: " + choices[2]);
  Serial.println("D: " + choices[3]);
}

void printQuestion(String question){
  Serial.println("\n" + question + "\n");
}

void loop() {
  String chosenAnswer = buttonManager->checkIfPressedButton();
  if(chosenAnswer != ""){
    Serial.println("\nAnswer: " + chosenAnswer + " ");
    Serial.print("Correct: ");
    if(questionManager->checkIfCorrectAnswer(chosenAnswer)){
      Serial.println("True");
    }
    else{
      Serial.println("False");
    }
    questionManager->nextQuestion();
    String* choices = getChoices();
    buttonManager->setChoices(choices);
    printQuestion(questionManager->getQuestion());
    printChoices(choices);
  }
  delay(100); 
}


$abcdeabcde151015202530354045505560fghijfghij