//#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
#include <Bounce2.h> //for buttons

// pins for DISTANCE SENSOR
#define PIN_TRIG 3
#define PIN_ECHO 2
// LDR Characteristics
const float GAMMA = 0.7;
const float RL10 = 50;

//Crear el objeto LCD con los pines correspondientes (rs, en, d4, d5, d6, d7)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

//buttons config
byte button_pins[] = {2, 3, 13}; // button pins, 2,3 = up/down, 13 = select
#define NUMBUTTONS sizeof(button_pins)
Bounce * buttons = new Bounce[NUMBUTTONS];

//menu config
#define MENU_SIZE 4
char *menu[MENU_SIZE] = { "Abrir", "Cerrar", "Conf.A", "Conf.C"};
int cursor = 0;
bool config = false;
int umbralAbrir = 15;
int umbralCerrar = 20;
int temp = 0;
int estado =0;


void setup() {
  //para usar la terminal
  Serial.begin(9600);
  iniciarPantalla();
  //iniciarSensorDistancia();
  iniciarBotones();
  mostrarMenu();



}


//functions ****************************

//LDR
float getLux() {
  int analogValue = analogRead(A0);
  float voltage = analogValue / 1024. * 5;
  float resistance = 2000 * voltage / (1 - voltage / 5);
  float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
  return lux;
}
//sensor distancia
int getDistanceCm() {
  // Start a new measurement:
  digitalWrite(PIN_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_TRIG, LOW);

  // Read the result: (divide by 58 to get cm, divide by 148 to get inches)
  int duration = pulseIn(PIN_ECHO, HIGH);
  //Serial.print("Distance in CM: ");
  //Serial.println(duration / 58);
  return duration / 58;
}

void iniciarSensorDistancia() {
  //distance sensor
  Serial.begin(115200);
  pinMode(PIN_TRIG, OUTPUT);
  pinMode(PIN_ECHO, INPUT);
}


//pantalla LCD 1602
void iniciarPantalla() {
  // Inicializar el LCD con el número de  columnas y filas del LCD
  lcd.begin(16, 2);
}

//botones
void iniciarBotones() {
  //buttons init
  // Make input & enable pull-up resistors on switch pins
  for (int i = 0; i < NUMBUTTONS; i++) {
    buttons[i].attach( button_pins[i], INPUT_PULLUP); // setup the bounce instance for the current button
    buttons[i].interval(25); // interval in ms
  }
}
void procesarBotonesMenu() {
  // process button press:
  for (int i = 0; i < NUMBUTTONS; i++) {
    Serial.print(cursor);
    buttons[i].update(); // Update the Bounce instance
    if ( buttons[i].fell() ) { // If it fell
      if (i == 2) { // select
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(">>");
        lcd.print(menu[cursor]);
        executeChoice(cursor);
      }
      else {
        // erase previous cursor:
        if (cursor >1 ) { //estabamos en el menu derecho
          lcd.setCursor(8, cursor-2);
          lcd.print(' ');
        } else {
          lcd.setCursor(0, cursor);
          lcd.print('>');
        }

        lcd.setCursor(0, cursor);
        lcd.print(' ');
        if (i == 0) { // up
          cursor++;
          if (cursor > (MENU_SIZE - 1)) cursor = 0;
        }
        else { // down
          cursor--;
          if (cursor < 0) cursor = (MENU_SIZE - 1);
        }
        // show cursor at new line:
        if (cursor > 1) { //show cursor for  right column
          lcd.setCursor(8, cursor-2);
          lcd.print('>');
        } else {
          lcd.setCursor(0, cursor);
          lcd.print('>');
        }
      }
    } // end if button fell...
  } // end for-loop of button check
}
void mostrarMenu() {
  cursor = 0;
  lcd.clear();
  // show menu items:
  for (int i = 0; i < MENU_SIZE; i++) {
    if (i < 2) { //limite a dos lineas de pantalla
      lcd.setCursor(2, i);
      lcd.print(menu[i]);
    } else {
      lcd.setCursor(9, i-2);
      lcd.print(menu[i]);
    }
  }
  lcd.setCursor(0, 0);
  lcd.print('>');
}

void showConfigMenu(String tipo) {
  lcd.clear();
  lcd.print("Conf. umbral ");
  lcd.print(tipo);
  lcd.setCursor(0,2);
  if (tipo == "abrir"){
  lcd.print(umbralAbrir);
  umbralAbrir = procesarBotonesConfig(umbralAbrir);
  }else if (tipo == "cerrar"){
    lcd.print(umbralCerrar);
    umbralCerrar = procesarBotonesConfig(umbralCerrar);
  }
  mostrarMenu();
}
/**
   Execute the task which matches the chosen menu item.
*/
void executeChoice(int choice) {
  switch (choice) {
    case 0 : //
      Serial.print("Execute choice "); Serial.print(choice); estado =1 /*abrir*/; Serial.println(menu[choice]);mostrarMenu();
      break;
    case 1 :
      Serial.print("Execute choice "); Serial.print(choice); estado=2 /*cerrar*/; Serial.println(menu[choice]);mostrarMenu();
      break;
    case 2 :
      Serial.print(choice);  Serial.println(menu[choice]); estado = 3 ; showConfigMenu("abrir");/*config*/;
      break;
    case 3 :
      Serial.print(choice);  Serial.println(menu[choice]); estado = 4 ; showConfigMenu("cerrar");/*configCerrar*/;
      break;
    default :
      Serial.print("Execute choice "); Serial.print(choice); Serial.print(" - "); Serial.println(menu[choice]);
      break;
  }

}

//********************** main loop    **********************
void loop() {
  procesarBotonesMenu();
 /* switch (estado){ //0 menu, 1- abrir, 2 -cerraar , 3 config
    case 3:
      showConfigMenu();
      umbralAbrir = procesarBotonesConfig(umbralAbrir);
      estado=0;
      break;
    case 0:
      mostrarMenu();
      procesarBotonesMenu();
      break;
  }*/
  
  //lcd.setCursor(0, 0);
  //lcd.print(getLux());

  //lcd.setCursor(0, 1);
  //lcd.print(getDistanceCm());

}


int procesarBotonesConfig(int valor) {
int valortemp=valor;
while (true){ //mientras no confirme
  for (int i = 0; i < NUMBUTTONS; i++) {
    buttons[i].update(); // Update the Bounce instance
    if ( buttons[i].fell() ) { // If it fell
      if (i == 2) {
        valor = valortemp;
        config = false;
        mostrarMenu();
        return valortemp;
         }
      if ( i == 0) {
        valortemp--;
        if (valortemp<0){
          valortemp=0;
        }
      }
      if (i == 1) {
        valortemp++;
      }
    }
    lcd.setCursor(0,2);
    lcd.print(valortemp);
    }
}
}