#include <Wire.h> // responsible for I2C communication
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include "time.h"
#include "sntp.h"

#define SCREEN_WIDTH 128 // define the screen width of OLED 
#define SCREEN_HEIGHT 64 // Height of the OLED 
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C

#define PB_CANCEL 34
#define PB_OK 32
#define PB_UP 33
#define PB_DOWN 35

#define NTP_SERVER     "pool.ntp.org"
#define UTC_OFFSET     19800
#define UTC_OFFSET_DST 0

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int days = 0;
int hours = 0;
int minutes = 0;
int seconds = 0;
int month = 0;
int year = 0;

int current_option = 0;
int max_options = 1;
String options[] = {"1) Set Time Zone"};

int UTC_offset = 0;

void print_line(String text, int size, int column, int row) { //print something in OLED display
  // we need to define these parameters before printing something in the OLED display
  display.setTextSize(size);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(column, row);
  display.println(text);
  display.display();
}

void update_time(void){
  struct tm timeinfo;
  getLocalTime(&timeinfo);

  char day_str[8];
  char hour_str[8];
  char min_str[8];
  char sec_str[8];
  char month_str[8]; 
  char year_str[8];
  
  strftime(day_str,8, "%d", &timeinfo);
  strftime(sec_str,8, "%S", &timeinfo);
  strftime(hour_str,8, "%I", &timeinfo);
  strftime(min_str,8, "%M", &timeinfo);
  strftime(month_str,8, "%m", &timeinfo); 
  strftime(year_str,8, "%Y", &timeinfo); 

  hours = atoi(hour_str);
  minutes = atoi(min_str);
  days = atoi(day_str);
  seconds = atoi(sec_str);
  month = atoi(month_str);
  year = atoi(year_str);
}

void print_date (void){
  display.clearDisplay(); 
  display.setCursor(0,0);
  display.setTextSize(1);
  display.print(String(days)+":"+String(month)+":"+String(year));

}

void print_time_now (void) { //Print the current time 
  //display.clearDisplay();
  print_line (String(hours)+":"+String(minutes)+":"+String(seconds), 2, 0, 10);

}



void setup(){

  Serial.begin(9600);

  WiFi.begin("Wokwi-GUEST", "", 6);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    display.clearDisplay();
    print_line("Connecting to WiFi..", 1, 0, 0);
  }
  
  display.clearDisplay();
  print_line("Connected to WiFi..", 1, 0, 0);

  
  configTime(UTC_OFFSET, UTC_OFFSET_DST, NTP_SERVER);


  if (! display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }

  display.display();// start the display
  delay(2000);

  display.clearDisplay();// clear the display

  print_line("Welcome to MediBox!", 1, 0, 0);
  delay(2000);

  display.clearDisplay();

}


void loop() {
  // put your main code here, to run repeatedly:
  update_time();
  print_time_now();
  print_date();
  if (digitalRead(PB_OK) == LOW){
    delay(200);
    go_to_menu();
  }
}

void go_to_menu(){ //Navigate throug the menu according to wait_for_button_press function
  while (digitalRead(PB_CANCEL) == HIGH ){
    display.clearDisplay();
    print_line(options[current_option], 1, 0, 0);

    int pressed_button = wait_for_button_press();
    if (pressed_button == PB_UP){
      delay(200);
      current_option += 1;
      current_option = current_option % max_options; //if current_option equals max_options then it will go back to option No 1
    }

    else if (pressed_button == PB_DOWN){
      delay(200);
      current_option -= 1;
      if (current_option < 0){ // Get rid of the negative numbers 
        current_option = max_options - 1;
      }
    }

    else if (pressed_button == PB_OK){
      delay(200);
      run_option(current_option);
    }
    
    else if (pressed_button == PB_CANCEL){
      delay(200);
      break;
    }
  }
}

int wait_for_button_press(){ //This returns the button user press. It returns a boolian value
  while(true){
    if (digitalRead(PB_UP) == LOW){
      delay(200);
      return(PB_UP);
    }

    else if (digitalRead(PB_OK) == LOW){
      delay(200);
      return(PB_OK);
    } 

    else if (digitalRead(PB_DOWN) == LOW){
      delay(200);
      return(PB_DOWN);
    }

    else if (digitalRead(PB_CANCEL) == LOW){
      delay(200);
      return(PB_CANCEL);
    }        
  }
}

void run_option (int option){ // Run a particular option argument is the number of option
  if (option == 0){
    set_time_zone();
  }
}

void set_time_zone(){
  // set the time(hour) 
  int temp_UTC_hours = 5;
  int final_offset_hours = 0;
  while (true){
    display.clearDisplay();
    print_line("Enter offset from UTC(hours) : " + String(temp_UTC_hours), 1, 0, 0); //display the current hour in the display

    int pressed_button = wait_for_button_press();
    if (pressed_button == PB_UP){
      delay(200);
      temp_UTC_hours += 1;
      temp_UTC_hours = temp_UTC_hours % 24;
    }

    else if (pressed_button == PB_DOWN){
      delay(200);
      temp_UTC_hours -= 1;
      if (temp_UTC_hours < 0){
        temp_UTC_hours = 23;
      }
    }

    else if (pressed_button == PB_OK){
      delay(200);
      final_offset_hours = temp_UTC_hours; 
      break;
    }

    else if (pressed_button == PB_CANCEL){
      delay(200);
      break;
    }  
  }

  int temp_UTC_minutes = 30;
  int final_offset_minutes = 0;
  while (true){
    display.clearDisplay();
    print_line("Enter offset from UTC(minutes) : " + String(temp_UTC_minutes), 1, 0, 0); //display the current hour in the display

    int pressed_button = wait_for_button_press();
    if (pressed_button == PB_UP){
      delay(200);
      temp_UTC_minutes += 1;
      temp_UTC_minutes = temp_UTC_minutes % 60;
    }

    else if (pressed_button == PB_DOWN){
      delay(200);
      temp_UTC_minutes -= 1;
      if (temp_UTC_minutes < 0){
        temp_UTC_minutes = 59;
      }
    }

    else if (pressed_button == PB_OK){
      delay(200);
      final_offset_minutes = temp_UTC_minutes; 
      break;
    }

    else if (pressed_button == PB_CANCEL){
      delay(200);
      break;
    }  
  }

  display.clearDisplay();
  print_line("Time is Set",1,0,0);
  UTC_offset = final_offset_hours*3600 + final_offset_minutes*60;
  configTime(UTC_offset, UTC_OFFSET_DST, NTP_SERVER);

}

void set_time(){
  // set the time(hour) 
  int temp_hours = hours;
  while (true){
    display.clearDisplay();
    print_line("Enter hour : " + String(temp_hours), 1, 0, 0); //display the current hour in the display

    int pressed_button = wait_for_button_press();
    if (pressed_button == PB_UP){
      delay(200);
      temp_hours += 1;
      temp_hours = temp_hours % 24;
    }

    else if (pressed_button == PB_DOWN){
      delay(200);
      temp_hours -= 1;
      if (temp_hours < 0){
        temp_hours = 23;
      }
    }

    else if (pressed_button == PB_OK){
      delay(200);
      hours = temp_hours; 
      break;
    }

    else if (pressed_button == PB_CANCEL){
      delay(200);
      break;
    }  
  }

  //set the time(minute)
  int temp_minutes = minutes;
  while (true){
    display.clearDisplay();
    print_line("Enter minute : " + String(temp_minutes), 1, 0, 0); //display the current hour in the display

    int pressed_button = wait_for_button_press();
    if (pressed_button == PB_UP){
      delay(200);
      temp_minutes += 1;
      temp_minutes = temp_minutes % 60;
    }

    else if (pressed_button == PB_DOWN){
      delay(200);
      temp_minutes -= 1;
      if (temp_minutes < 0){
        temp_minutes = 59;
      }
    }

    else if (pressed_button == PB_OK){
      delay(200);
      minutes = temp_minutes;
      break;
    }

    else if (pressed_button == PB_CANCEL){
      delay(200);
      break;
    }  
  }

  display.clearDisplay();
  print_line("Time is set", 1, 0, 0);
  delay(1000);
}
$abcdeabcde151015202530354045505560fghijfghij