#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>


/*
I2C display menu
*/

// Reset pin not used but needed for library
#define OLED_RESET 5
Adafruit_SSD1306 display(OLED_RESET);

//Rotary encoder pins
#define ENCODER_CLK 2
#define ENCODER_DT  4
#define ENCODER_BTN 3

const int SHORT_PRESS_TIME = 1000;

int analogPin0 = A0; // pot wiper connected to analog pin 0

int menuItem = 0; //Menu Item to be displayed

bool set_mode = 0; //if true the screen corresponding settings can be modified

int setValue = 0; //Set Value to be applied

// Default Settings
bool setting1 = false ;
int setting2 = 0 ;
int setting3 = 0 ;


unsigned long releaseTime = 0;

void setup() {


  //Set encoder pins as inputs
  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT, INPUT);
  pinMode(ENCODER_BTN, INPUT_PULLUP);

  //Attaching interupts on encoder events 
  attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoderRot, FALLING);
  attachInterrupt(digitalPinToInterrupt(ENCODER_BTN), readEncoderBut, CHANGE);

  // Start Wire library for I2C
  Wire.begin();

  
  // initialize OLED with I2C addr 0x3C
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  

}

int get_encoderCounter() {  // Get the menuItem value, disabling interrupts.
  int result;
  noInterrupts();
  result = menuItem;
  interrupts();
  return result;
}

int get_setValue() {  // Get the setting set value, disabling interrupts.
  int result;
  noInterrupts();
  result = setValue;
  interrupts();
  return result;
}

void readEncoderRot() {  //Read encoder Rotation
  int dtValue = digitalRead(ENCODER_DT);
  if (dtValue == HIGH) {
    digitalWrite(LED_BUILTIN, HIGH);//Next Menu Item "Rotated clockwise "
    if (set_mode) {
      setValue++ ;
    }
    else {
      menuItem++ ;
    }
  }
  if (dtValue == LOW) {
    digitalWrite(LED_BUILTIN, HIGH);//Previous Menu Item "Rotated counterclockwise"
    if (set_mode) {
      setValue-- ;
    }
    else {
      menuItem-- ;
    }
  }
}

void readEncoderBut() {  //Read encoder button press
/*
int lastState = HIGH;  // the previous state from the input pin
int currentState;     // the current reading from the input pin
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;

currentState = digitalRead(ENCODER_BTN);

  if(lastState == HIGH && currentState == LOW) {        // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if(lastState == LOW && currentState == HIGH) { // button is released
    isPressing = false;
    releasedTime = millis();

        long pressDuration = releasedTime - pressedTime;
    if( pressDuration < SHORT_PRESS_TIME )
      digitalWrite(LED_BUILTIN, HIGH); //press action
      //escape
      //Serial.println("A short press is detected");
  }
    if(isPressing == true && isLongDetected == false) {
    long pressDuration = millis() - pressedTime;

    if( pressDuration > SHORT_PRESS_TIME ) {
      //Serial.println("A long press is detected");
      isLongDetected = true;
      set_mode = !set_mode;
    }
  }
  lastState = currentState;
*/

pressTime = millis();
  //if (digitalRead(ENCODER_BTN) == LOW) { //press event
  //pressedTime = millis();
      while ((digitalRead(ENCODER_BTN) == LOW) ) { //release event
       delay (10);
      }
  //}
releaseTime = millis():
  if ((releaseTime - pressTime) > 1000){
    set_mode = !set_mode;
  }
  else {
    digitalWrite(LED_BUILTIN, HIGH);
  }

  //set_mode = !set_mode;
  //if (set_mode){
  //  digitalWrite(LED_BUILTIN, HIGH); //press action
  //}
  //else{
  //  digitalWrite(LED_BUILTIN, LOW); //press action
  //}
  //}

}

float readSensor(){  //Read sensor and return value (float)
  float val;
  return val = analogRead(analogPin0); // read the input pin
}

void screen0(){   //Handle screen0
  float val;
  int setting = setting1 ; //Retrieve default (or saved) setting
  if (set_mode){
    setting = get_setValue();
  }
  val = readSensor();
  displayItem("screen0",val, setting);
  digitalWrite(LED_BUILTIN, LOW);
  setting1 = setting; //Save modified setting
}

void screen1(){   //Handle screen1
  float val;
  int setting = setting1 ; //Retrieve default (or saved) setting
  if (set_mode){
    setting = get_setValue();
  }
  val = readSensor();
  displayItem("screen1",val, setting);
  digitalWrite(LED_BUILTIN, LOW);
  setting1 = setting; //Save modified setting
}

void screen2(){    //Handle screen2
  int val, setting = 0;
  val = readSensor();
  displayItem("screen2",val, setting);
  digitalWrite(LED_BUILTIN, LOW);
}

void screen3(){    //Handle screen3
  int val, setting = 0;
  val = readSensor(); // read the input pin
  displayItem("screen3",val, setting);
  digitalWrite(LED_BUILTIN, LOW); 
}

int displayItem(String name, float value, int setting){  //Display item according to the provided parameters
  
  display.clearDisplay(); // Clear the display
  display.setTextColor(WHITE); //Set the color - always use white despite actual display color
  display.setTextSize(1); //Set the font size
  
  display.setCursor(0,0); //Set the cursor coordinates
  display.print(name);
  display.setCursor(0,20); 
  display.setTextSize(1); //Set the font size
  //display.print(pressedTime);
  //display.print("   ");
  display.print(releaseTime);
  //display.print(setting);
  display.setCursor(0,25);
  if (set_mode){
    display.invertDisplay(true);
  }
  else {
    display.invertDisplay(false);
  }

}

void displayMenuItem(int cursor) {   // Select the screen to be displayed
  switch (cursor) {
  case -1:             // When out of bounds
    menuItem = 3;      // 
    screen3();         // ..go to the last screen
    break;  
  case 0:              // Default screen menuItem0
    screen0();
    break;
  case 1:              //If menuItem == 1 display screen2
    screen1();
    break;
  case 2:
    screen2();
    break;
  case 3:
    screen3(); 
    break;
  case 4:
    menuItem = 0;
    screen0(); 
    break;
  default:
    menuItem = 0;
    screen0();
    break;}
}

void loop() {
  displayMenuItem(get_encoderCounter());
  display.display();
}