/*
  ESP32 Chuck Norris Jokes
  by R. Pelayo
  Tutorial: https://www.teachmemicro.com/esp32-restful-api
  
  V1.0 - 10/27/2020
*/

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



const char* ssid = "ATT2PQv2U8";
const char* password = "PASSWORD"; // fill in password

String response = ""; //String for storing server response

JsonDocument myDoc;

// ------------------ Start U8g2 library and constructor ---------------------------------

#include "U8g2lib.h"

// Constructor for U8g2lib
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);

// ------------------ Start generated bitmaps from image2cpp ---------------------------------

// 'Sunrise_Sunset_Icon', 16x16px
const unsigned char Sunrise_Sunset_Icon[] PROGMEM = { // 'PROGMEM" places this variable in Flash (32k) memory as opposed to SRAM (2k)
	0x88, 0x00, 0x72, 0x02, 0x8c, 0x01, 0x05, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x05, 0x45, 
	0x8c, 0xc1, 0x72, 0xc2, 0x88, 0xe0, 0x00, 0xf0, 0x00, 0x78, 0x00, 0x7c, 0xc0, 0x3f, 0x00, 0x0f
};

// 'Dad_Jokes_Icon', 16x16px
const unsigned char Dad_Jokes_Icon[] PROGMEM = {
	0xc0, 0x03, 0x30, 0x0c, 0x0c, 0x30, 0x04, 0x20, 0x72, 0x4e, 0x22, 0x44, 0x01, 0x80, 0x01, 0x80, 
	0x01, 0x80, 0x19, 0x98, 0xf2, 0x4f, 0xe2, 0x47, 0x84, 0x21, 0x0c, 0x30, 0x30, 0x0c, 0xc0, 0x03
};

// 'Useless_Facts_Icon', 16x16px
const unsigned char Useless_Facts_Icon[] PROGMEM = {
	0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x07, 
	0x80, 0x03, 0x87, 0x03, 0xcf, 0x01, 0xde, 0x01, 0xfc, 0x00, 0xf8, 0x00, 0x70, 0x00, 0x20, 0x00
};

// 'Quote_Icon', 16x16px
const unsigned char Quote_Icon[] PROGMEM = {
	0xcf, 0x03, 0xcf, 0x03, 0xcf, 0x03, 0xc3, 0x00, 0xc3, 0x00, 0x86, 0x01, 0x0c, 0x03, 0x00, 0x00, 
	0x00, 0x00, 0xc0, 0xf3, 0xc0, 0xf3, 0xc0, 0xf3, 0x00, 0xc3, 0x00, 0xc3, 0x80, 0x61, 0xc0, 0x30
};

// 'Chuck_Icon_new', 16x16px
const unsigned char Chuck_Icon[] PROGMEM = {
	0x00, 0x00, 0x42, 0x42, 0xa2, 0x45, 0x16, 0x68, 0xfc, 0x3f, 0x08, 0x10, 0x68, 0x16, 0x08, 0x10, 
	0x08, 0x11, 0x88, 0x11, 0x08, 0x10, 0xc8, 0x13, 0x28, 0x14, 0x08, 0x10, 0x50, 0x0a, 0xa0, 0x05
};

// Array of all icon bitmaps.
const unsigned char* menu_icon[5] = {
	Sunrise_Sunset_Icon,
	Dad_Jokes_Icon,
	Useless_Facts_Icon,
	Quote_Icon,
	Chuck_Icon
};

// 'Boarder', 128x20px
const unsigned char Boarder[] PROGMEM = {
	0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 
	0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 
	0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 
	0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01
};

// 'Scroll Bar', 8x64px
const unsigned char Scroll_Bar[] PROGMEM = {
	0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 
	0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 
	0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 
	0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40
};

// 2D array of strings for menu items
const int NUM_ITEMS = 5;
char menu_item[NUM_ITEMS][20] = {
	{"Sunrise Sunset"},
	{"Dad Jokes"},
	{"Useless Facts"},
	{"Quotes"},
	{"Chuck Jokes"}
};

// ------------------ End generated bitmaps from image2cpp ---------------------------------

// ------------------ Start OLED menu variables ---------------------------------

int item_sel_previous; // menu item before selected
int item_selected = 0; // selected menu item
int item_sel_next; // menu item after selected


#define BUTTON_UP_PIN 27 // pin for UP button 
#define BUTTON_DOWN_PIN 26 // pin for DOWN button
#define BUTTON_SELECT_PIN 25 // pin for SELECT button


int button_up_clicked = 0; // only perform action when button is clicked, and wait until another press
int button_select_clicked = 0; // same as above
int button_down_clicked = 0; // same as above

int current_screen = 0;   // 0 = menu, 1 = screenshot, 2 = qr

// ------------------ End OLED menu variables ---------------------------------


/* ----------------------- Start scrolling text variables ----------------------------- */

u8g2_uint_t offset;			// current offset for the scrolling text
u8g2_uint_t width;			// pixel width of the scrolling text (must be lesser than 128 unless U8G2_16BIT is defined
const char *text = "\"We could never learn to be brave and patient if there were only joy in the world.\" ";

/* ----------------------- End scrolling text variables ----------------------------- */



void setup(void) {
  Serial.begin(9600);

  /* ----------------------- Start WiFi connection ----------------------------- */
  /*
  WiFi.mode(WIFI_STA);
  WiFi.begin("Wokwi-GUEST", "", 6);
  //WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("WiFi connected with IP: ");
  Serial.println(WiFi.localIP());
  */
  /* ----------------------- End WiFi connection ----------------------------- */

  /* ----------------------- Start u8g2 setup ----------------------------- */
  u8g2.begin();
	u8g2.setBitmapMode(1);
  u8g2.setColorIndex(1);  // set the color to white

	/* ---------- Used for scrolling text ---------- */
	u8g2.setFont(u8g2_font_10x20_mr);
  width = u8g2.getUTF8Width(text);
  u8g2.setFontMode(0);		// enable transparent mode, which is faster
	/* ------------------------ End u8g2 setup ------------------------------ */

  /* ---------------- Button setup ----------------- */
  pinMode(BUTTON_UP_PIN, INPUT_PULLUP); // up button
  pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP); // down button
  pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP); // select button
  
}

void loop(void) {



  /* ----------------------- Start API menu ----------------------------- */
  u8g2_uint_t x;

	if (current_screen == 0) { // MENU SCREEN

		if ((digitalRead(BUTTON_UP_PIN) == LOW) && (button_up_clicked == 0)) { // up button pressed
    	item_selected = item_selected - 1; // select previous item
    	button_up_clicked = 1; // set button to clicked to only perform the action once
    	if (item_selected < 0) { // if first item was selected, jump to last item
      	item_selected = NUM_ITEMS - 1;
    	}
  	}

  	if ((digitalRead(BUTTON_DOWN_PIN) == LOW) && (button_down_clicked == 0)) { // down button pressed
    	item_selected = item_selected + 1; // select next item
    	button_down_clicked = 1; // set button to clicked to only perform the action once
    	if (item_selected >= NUM_ITEMS) { // last item was selected, jump to first menu item
      	item_selected = 0;
    	}
  	}

		if ((digitalRead(BUTTON_UP_PIN) == HIGH) && (button_up_clicked == 1)) { // unclick 
    	button_up_clicked = 0;
  	}
  	if ((digitalRead(BUTTON_DOWN_PIN) == HIGH) && (button_down_clicked == 1)) { // unclick
    	button_down_clicked = 0;
  	}

	}


	// This section toggles through enter button selections by changing variable 'current_screen' value to 0, 1 or 2
	if ((digitalRead(BUTTON_SELECT_PIN) == LOW) && (button_select_clicked == 0)) { // select button clicked, jump between screens
     button_select_clicked = 1; // set button to clicked to only perform the action once
     if (current_screen == 0) {current_screen = 1;} // menu items screen --> screenshots screen
     else if (current_screen == 1) {current_screen = 2;} // screenshots screen --> qr codes screen
     else {current_screen = 0;} // qr codes screen --> menu items screen
  }
  if ((digitalRead(BUTTON_SELECT_PIN) == HIGH) && (button_select_clicked == 1)) { // unclick 
    button_select_clicked = 0;
  }



	// set correct values for the previous and next items
	item_sel_previous = item_selected - 1; // = 0 - 1 or -1
  if (item_sel_previous < 0) { // Yes, -1 is < 0
		item_sel_previous = NUM_ITEMS - 1; // NUM_ITEMS(4) - 1 = 3
	}

  item_sel_next = item_selected + 1; // = 0 + 1 or 1
  if (item_sel_next >= NUM_ITEMS) { // No, 1 is not > 4
		item_sel_next = 0; // next item would be after last = make it the first
	} 


  u8g2.firstPage(); // required for page drawing, mode 1
  do {

		if (current_screen == 0) { // MENU SCREEN
    
			// selected menu item boarder
			u8g2.drawXBMP( 0, 22, 128, 20, Boarder);

			// draw previous item as icon + label
			u8g2.setFont(u8g2_font_7x14_tf);
			u8g2.drawStr(26, 15, menu_item[item_sel_previous]);
			// From top left corner - over, down, horz size, vert size)
			// u8g2.drawXBMP(, over, down, horz, vert);
			u8g2.drawXBMP(4, 2, 16, 16, menu_icon[item_sel_previous]);

			// draw selected item as icon + label in bold font
			u8g2.setFont(u8g2_font_7x14B_tf);
			u8g2.drawStr(25, 37, menu_item[item_selected]);
			u8g2.drawXBMP(4, 24, 16, 16, menu_icon[item_selected]);

			// draw next item as icon + label
			u8g2.setFont(u8g2_font_7x14_tf);
			u8g2.drawStr(26, 59, menu_item[item_sel_next]);
			u8g2.drawXBMP(4, 46, 16, 16, menu_icon[item_sel_next]);

			// draw scrollbar background
			u8g2.drawXBMP(120, 0, 8, 64, Scroll_Bar);

			// draw scrollbar handle
			u8g2.drawBox(125, 64/NUM_ITEMS * item_selected, 3, 64/NUM_ITEMS);
		}

		// ---------- Run 'Scrolling Quote' Test ----------

		else if (current_screen == 1) { // MENU OPEN SCREEN
      u8g2.firstPage();
  		do {
    		// draw the scrolling text at current offset
    		x = offset;
    		u8g2.setFont(u8g2_font_10x20_mr);		// set the target font

    		do { // repeated drawing of the scrolling text...
      		u8g2.drawUTF8(x, 30, text); // draw the scolling text
      		x += width;	// add the pixel width of the scrolling text
    		} while( x < u8g2.getDisplayWidth() ); // draw again until the complete display is filled
    
    		u8g2.setFont(u8g2_font_10x20_mr);		// draw the current pixel width
    		u8g2.setCursor(0, 58);
    		u8g2.print(width);					// this value must be lesser than 128 unless U8G2_16BIT is set
    
  		} while ( u8g2.nextPage() );
  
  		offset-=10;	// scroll by one pixel
  		if ( (u8g2_uint_t)offset < (u8g2_uint_t)-width )	
    		offset = 0;	// start over again
    	}



    	else if (current_screen == 2) { // SUB MENU OPEN SCREEN
      // Do something - "Display second item"
    	}


  } while ( u8g2.nextPage() ); // required for page drawing, mode 1




/*


  // -------- Start http request and response ----------
  HTTPClient http; //Initiate HTTP client
  //The API URL
  String request = "https://api.chucknorris.io/jokes/random";
  
  http.begin(request); //Start the request
  
  http.GET(); //Use HTTP GET request
  
  response = http.getString(); //Response from server
  
  //Parse JSON, read error if any
  DeserializationError error = deserializeJson(myDoc, response); // DeserializationError converts to boolean
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
  }
  else {
    Serial.print(F("deserializeJson() passed: "));
    Serial.println(error.f_str());
  }

  // Serial.println(response);
  String value = myDoc["value"];

  Serial.println(value);
  
  //Print parsed value on Serial Monitor
  //Serial.println(response["value"].as<char*>());
  
  //Close connection  
  http.end();
  //Wait two seconds for next joke

  // -------- End http request and response ---------- 
  

  */

  delay(1000);



}