#define LIBRARY 0 //Set to 0 for U8g2lib and 1 to use Adafruit_GFX
#include <Midi.h> // library for midi ble server
#include <Deneyap_DerinlikOlcer.h> // vl530x laser distance sensor library
#include <sm.h> // my own library for make simple menus
#include <tb.h> //my own libray for use capacitive touch pins


//section for define define all about menu system
U8G2_SSD1306_128X64_NONAME_F_HW_I2C display(U8G2_R0,U8X8_PIN_NONE); // initialitation for display 0.96 128x64

tb key1(T0,60);
tb key2(T2,60); 
tb key3(T3,60); 
tb key4(T4,60);
tb btn1(T8);
tb btn2(T9);

sm Menu(display); // define menu

 txtMenu Main[]= {
    "Menu",
    "Play",
    "Config"
  };

txtMenu Config[]= {
    "Config",
    "Laser Led",
    "Exit"
  };

MidiBleServer ble("AirDion");
int amplitude = 100; // 0 to 128

// 
int lastNote = 0; // 0 to 128
// tiempo de espera para considerar que la mano está quieta (en ms)
const int QUIET_TIME = 500;
// variable para almacenar la distancia anterior
long lastDistance = 0;
// variable para almacenar el estado del botón
bool btnState = false;
// variable para almacenar la dirección de la acción
int direction = 0;
int lastDirection = 0;
// variable para almacenar el estado de la acción
bool action = false;
// variable para almacenar la nota MIDI enviada
// variable para almacenar el tiempo de la última acción
unsigned long lastTimeSensor = 0;
bool laserState=false;
TofRangeFinder sensor; 


enum {  menu ,  play} modo; 

void setup() {
  pinMode(5,OUTPUT);
   Serial.begin(115200);
   ble.begin();  
  ble.setDefaultSendingChannel(0);
  sensor.begin(0x29); //initalize sensor 
  display.begin(); //initialize display
  Menu.SetAutoOff(60);
  Menu.alignTitle=CENTER;
  Menu.alignItem=LEFT;
  Menu.Root(Main,"Main");
  Menu.Message("Make some|noise Contest|Instructables|2023",CENTER); 
  Menu.Message("AirDion| |By: Holman|2023",CENTER); 
  
  modo=menu;

}


void loop() {
 key1.update();
 key2.update();
 key3.update();
 key4.update();
 btn1.update();
 btn2.update();
    if(modo==play)
  {   
      
      // read state of buttons
       bool k1=key1.isTouched();
       bool k2=key2.isTouched();
       bool k3=key3.isTouched();
       bool k4=key4.isTouched();
        
          
      long distance = sensor.ReadDistance();
      
    
    // calculate direction
    if (distance > lastDistance) {
      direction = 1;
    } else if (distance < lastDistance) {
      direction = -1;
    }
    if((k1 && !k2 && !k3 && !k4) && direction==1 && !action){ lastNote=60; } //C
    else if((k1 && !k2 && !k3 && !k4) && direction==-1 && !action){ lastNote=62;} //D
    
    else if((!k1 && k2 && !k3 && !k4) && direction==1 && !action){ lastNote=64; } //E
    else if((!k1 && k2 && !k3 && !k4) && direction==-1 && !action){ lastNote=65; } //F

    else if((!k1 && !k2 && k3 && !k4) && direction==1 && !action){ lastNote=67; } //G
    else if((!k1 && !k2 && k3 && !k4) && direction==-1 && !action){ lastNote=69;} //A

    else if((!k1 && !k2 && !k3 && k4) && direction==1 && !action){ lastNote=71; } //B
    else if((!k1 && !k2 && !k3 && k4) && direction==-1 && !action){ lastNote=72; } //D

    else if((k1 && k2 && !k3 && !k4) && direction==1 && !action){ lastNote=61; } //C#
    else if((k1 && k2 && !k3 && !k4) && direction==-1 && !action){ lastNote=63; } //D#

    else if((!k1 && k2 && k3 && !k4) && direction==1 && !action){ lastNote=66; } //F#
    else if((!k1 && k2 && k3 && !k4) && direction==-1 && !action){ lastNote=68; } //G#

    else if((!k1 && !k2 && k3 && k4) && direction==1 && !action){ lastNote=70; } //A#
    else if(btn1.isTouched() && btn2.isTouched()) { Menu.Message("AIRDION| |Back to|Menu",CENTER);  modo=menu;}
    
    
    if (!action){ ble.noteOn( lastNote, amplitude );  lastDirection = direction; action=true; }
          // si se presiona el botón y se ha cambiado de dirección
     if(direction != lastDirection){  ble.noteOff( lastNote, amplitude ); action=false; }
    // si se suelta el botón o la mano se queda quieta
     if ((!k1 && !k2 && !k3 && !k4 ) || (millis() - lastTimeSensor > QUIET_TIME && lastDistance == distance)) {
         // enviar mensaje note off con valor decreciente de velocidad
            ble.noteOff(lastNote, amplitude );             
           action = false;
     } 
     
     
     
      // actualizar distancia anterior y tiempo de la última acción
    lastDistance = distance;
    lastTimeSensor = millis();
  }


  // mode menu for navigate options
  else if(modo==menu){
    
     bool up=btn1.isClicks(1);
     bool down=btn2.isClicks(1);
     bool enter=key1.isClicks(1);
     if(up){Menu.Up();  }
     if(down){Menu.Down(); }
     else if(enter && Menu.Select(1,"Main")){ Menu.Message("AIRDION| |PLAY MODE",CENTER);  modo=play;}
     else if(enter && Menu.Select(2,"Main")){ Menu.Assign(Config,"Conf");}

     else if(enter && Menu.Select(1,"Conf")){ if(laserState==false){ Menu.Message("Laser Led| |ON",CENTER,1000);laserState=true; digitalWrite(5,HIGH); }else{  Menu.Message("Laser Led| |OFF",CENTER,1000);laserState=false;  digitalWrite(5,LOW); }  }
     else if(enter && Menu.Select(2,"Conf")){ Menu.Root();}
         
 
    Menu.Show();
    }

}
