#include <Arduino.h>

#include <LiquidCrystal_I2C.h>
#include <OneButton.h>
#include <RotaryEncoder.h>
#define DT 3
#define CLK 2
#define BUTTON 18
LiquidCrystal_I2C lcd(0x27, 20, 4);
RotaryEncoder *encoder = new RotaryEncoder(DT, CLK, RotaryEncoder::LatchMode::FOUR0);
OneButton *bSelect = new OneButton(BUTTON, true, true);


bool stop(1);
int newPos(0);
int pos(0);
uint8_t mMenu(0);
uint8_t tab(0);
uint8_t pSelect(0);
uint8_t pSelect1(0);
uint8_t pSelect2(0);
uint32_t head (0);
uint32_t length (0);
uint32_t quatity (0);

byte wifi[8] = {0x00,0x0E,0x11,0x04,0x0A,0x00,0x04,0x00};
byte blynk[8] = {0x1E,0x11,0x11,0x1F,0x11,0x11,0x11,0x1E};
byte arrow[8] = {0x00,0x00,0x04,0x06,0x1F,0x06,0x04,0x00};
byte disconnect[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

void setcur(uint8_t row, uint8_t col);
void clearcur(uint8_t row, uint8_t col);
void value (uint32_t& _value, uint8_t _step);
uint8_t Pos(uint8_t MIN, uint8_t MAX,uint8_t STEP);
void Dmenu(uint8_t& t_menu,uint8_t& m_menu);
void click();
void doubleclick();
void longpress();
void checkrotary();
void checkbutton();
void mainMenu();
void nextMenu();
void configMenu();
void connectMenu();
void setup() {

Serial.begin(115200);


lcd.init();
lcd.createChar(0, wifi);
lcd.createChar(1, blynk);
lcd.createChar(2, arrow);
lcd.createChar(3, disconnect);
lcd.backlight();

bSelect->attachClick(click);
bSelect->attachDoubleClick(doubleclick);
bSelect->attachLongPressStart(longpress);

attachInterrupt(digitalPinToInterrupt(CLK),checkrotary,CHANGE);
attachInterrupt(digitalPinToInterrupt(DT),checkrotary,CHANGE);
attachInterrupt(digitalPinToInterrupt(BUTTON),checkbutton,CHANGE);

}

void loop() {
  // put your main code here, to run repeatedly:
  encoder->tick();
  bSelect->tick();
  Dmenu();

}

void checkrotary(){
  encoder->tick();
}

void checkbutton(){
  bSelect->tick();

}

void click(){
  
  if(tab==0 && mMenu==0 && pSelect==0) {mMenu=1;lcd.clear();}
  else if(tab==0 && mMenu==1 && pSelect==0) {mMenu=0;encoder->setPosition(0);lcd.clear();}

  else if(tab==0 && mMenu==0 && pSelect==1) {mMenu=2;lcd.clear();}
  else if(tab==0 && mMenu==2 && pSelect==1) {mMenu=0;encoder->setPosition(2);lcd.clear();}

  else if(tab==0 && mMenu==0 && pSelect==2) {mMenu=3;lcd.clear();}
  else if(tab==0 && mMenu==3 && pSelect==2) {mMenu=0;encoder->setPosition(4);lcd.clear();}

  else if(tab==0 && mMenu==0 && pSelect==3) {mMenu=4;lcd.clear();}
  else if(tab==0 && mMenu==0 && pSelect==4) {mMenu=5;lcd.clear();}



  else if(tab==1 && mMenu==0 && pSelect==1) {stop = 0;}
  else if(tab==1 && mMenu==0 && pSelect==2) {stop = 1;}
}

void doubleclick(){
  if(tab == 0){
    if(mMenu==4||mMenu==5){
      mMenu = 0;
      lcd.clear();
    }
  }
}

void longpress(){
  if (stop){
    if (tab==0 && mMenu==0 || tab==0 && mMenu==4 ||tab==1){
      tab++;
      lcd.clear();
      if(tab >= 2) {tab = 0;}
      
      if (tab==0){encoder->setPosition(pSelect*2);}
    }
    
  }
}

void setcur(uint8_t row, uint8_t col){
  lcd.setCursor(row,col);
  lcd.write(byte(2));
}

void clearcur(uint8_t row, uint8_t col){
  lcd.setCursor(row,col);
  lcd.write(byte(3));
}

void value (uint32_t& _value, uint8_t _step){
  newPos = encoder->getPosition();
  if (newPos != pos) 
  {
    if((int)encoder->getDirection() == 1) 
    {
      
      if (_value == 99999) _value = 99999 ;
      else _value += _step;
    }
    else 
    {
      if (_value == 0) _value = 0;
      else _value -= _step;
    }
    pos = newPos;
  }
}

uint8_t Pos(uint8_t MIN, uint8_t MAX,uint8_t STEP){
  uint8_t newPos = encoder->getPosition() / STEP;
  if (newPos < MIN) {
    encoder->setPosition(MAX);
    newPos = MAX;
  } 
  else if (newPos > MAX) {
    encoder->setPosition(MIN);
    newPos = MIN;
  }
  return newPos;
}
void mainMenu(){
  lcd.setCursor(1,0);
  lcd.print("HEAD   : "+String(head)+" mm");
  lcd.setCursor(1,1);
  lcd.print("LENGTH : "+String(length)+" mm");
  lcd.setCursor(1,2);
  lcd.print("QUATITY: "+String(quatity)+" pcs");
  lcd.setCursor(2,3);
  lcd.print("<NEXT>");
  lcd.setCursor(12,3);
  lcd.print("<WIFI>");
  pSelect=Pos(0,4,2);
  switch (pSelect){
    case 0:
      setcur(0,0);
      clearcur(0,1);
      clearcur(0,2);
      clearcur(1,3);
      clearcur(9,3);
      break;
    case 1:
      clearcur(0,0);
      setcur(0,1);
      clearcur(0,2);
      clearcur(1,3);
      clearcur(9,3);
      break;
    case 2:
      clearcur(0,0);
      clearcur(0,1);
      setcur(0,2);
      clearcur(1,3);
      clearcur(9,3);
      break;
    case 3:
      clearcur(0,0);
      clearcur(0,1);
      clearcur(0,2);
      setcur(1,3);
      clearcur(9,3);
      break;
    case 4:
      clearcur(0,0);
      clearcur(0,1);
      clearcur(0,2);
      clearcur(1,3);
      setcur(9,3);
      break;
  };
}

void nextMenu();
void configMenu();
void connectMenu();
void Dmenu(){
  switch (tab){
    case 0: 
        switch(mMenu){
          case 0:
          //menu chính
            mainMenu();
            break;

          case 1:
          //thay đổi head
            lcd.setCursor(1,0);
            lcd.print("HEAD   : "+String(head)+" mm");
            value(head,1);
            break;
          
          case 2:
          //thay đôi length
            lcd.setCursor(1,1);
            lcd.print("LENGTH : "+String(length)+" mm");
            value(length,1);
            break;

          case 3:
          //thay đổi số lượng
            lcd.setCursor(1,2);
            lcd.print("QUATITY: "+String(quatity)+" pcs");
            value(quatity,1);
            break;

          case 4:
            lcd.setCursor(0,0);
            lcd.print("MENU OFFSET");
            break;
          case 5:
            lcd.setCursor(0,0);
            lcd.print("MENU:");
            lcd.setCursor(1,1);
            lcd.print("CONNECT");
            lcd.setCursor(1,2);
            lcd.print("RESET");
            //pSelect1=Pos(1,2,2);

            break;
        };


      break;
    case 1:
      switch(mMenu){
          case 0:
          case 4:
            lcd.setCursor(0,0);
            lcd.print("Run");
            lcd.setCursor(1,1);
            lcd.print(String(quatity)+"/"+String(quatity));
            lcd.setCursor(1,2);
            lcd.print("STOP");
            pSelect2=Pos(1,2,2);
            break;
        };
      break;

  };
  
}