//Arduino Code - Rotary Encoder w push button
/*
TODO:
-Edit mode             <==
-second input (or more) |=> more possibilities => ability to scroll 
-working sd card save
  -should be easy?
  -file handling
-undo/redo

*/


#include <BfButton.h>
#include "SimpleMenu.h"
#include <LiquidCrystal.h>
#include <LcdProgressBar.h>

int btnPin=6; //GPIO #3-Push button on encoder
int DT=5; //GPIO #4-DT on encoder (Output B)
int CLK=4; //GPIO #5-CLK on encoder (Output A)
BfButton btn(BfButton::STANDALONE_DIGITAL, btnPin, true, LOW);
BfButton btn2(BfButton::STANDALONE_DIGITAL, 3, true, LOW);

#define LCD_RS 12
#define LCD_EN 11
#define LCD_D4 10
#define LCD_D5 9
#define LCD_D6 8
#define LCD_D7 7
String userText = "";
int currentStateCLK;
int lastStateCLK;
int charPos = 0;
int cursorPos = 0;
int minCursorX;
int minCursorY;
int  sensitivity = 0;
int rotarDelay = 0;
byte  lcdNumCols = 16; // -- number of columns in the LCD
const int alphabetSize = 26;
char lowerCase[alphabetSize];
char upperCase[alphabetSize];


enum MenuStates
{
  MainMenu,
  Sensitivity,
  Write
};

enum CharacterCase
{
  Uppercase,
  Lowercase,
};

CharacterCase CharCase = Lowercase;
MenuStates State = MainMenu;

LiquidCrystal lcd = LiquidCrystal(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
LcdProgressBar lpg(&lcd, 1, lcdNumCols);

void Foo(){
  Serial.println("dostuff");
}

SimpleMenu MenuSub[3] = {
  SimpleMenu("Sensitivity",setSensitivity),
  SimpleMenu("Char map",Foo),
  SimpleMenu("Credits",Credits)
};

SimpleMenu Menu[3] = {
  SimpleMenu("Write mode",writeMode),
  SimpleMenu("Settings",3,MenuSub),
  SimpleMenu("Save to SD",Foo)
};

SimpleMenu TopMenu(3,Menu);

void setSensitivity()
{
  btn.read(); 
  State = Sensitivity;
  drawPgsBar();
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(CLK,INPUT_PULLUP);
  pinMode(DT,INPUT_PULLUP);
  lcd.begin(16, 2);

  for (int i = 0; i < alphabetSize; i++) {
        lowerCase[i] = 'a' + i;
    }
        for (int i = 0; i < alphabetSize; i++) {
        upperCase[i] = 'A' + i;
    }
//Button settings
  btn.onPress(pressHandler)
    .onDoublePress(pressHandler) // default timeout
    .onPressFor(pressHandler, 500); // custom timeout for 1 second

  btn2.onPress(pressHandler2)
    .onDoublePress(pressHandler2) // default timeout
    .onPressFor(pressHandler2, 500); // custom timeout for 1 second
  lpg.setMinValue(0);
  lpg.setMaxValue(8);
  lcd.println("Wordman 1.0");
  lcd.setCursor(0,1);
  lcd.print("lcd edition");
  delay(1500);
  lcd.clear();
  TopMenu.begin(display);
}

//Button press hanlding function
void pressHandler (BfButton *btn2, BfButton::press_pattern_t pattern) {
  switch (pattern) {
    case BfButton::SINGLE_PRESS:
          switch(State){
         case MainMenu:
         lcd.clear();
          TopMenu.select();
          break;
         case Write:
            switch(CharCase){
            case Uppercase:
            userText += upperCase[charPos];
            break;
            case Lowercase:
            userText += lowerCase[charPos];
            break;
            }
          cursorPos++;
          Serial.println("Char moved");
          Serial.println(userText);
          break;
          }
      Serial.println("Single push");
      break;
      
    case BfButton::DOUBLE_PRESS:
      Serial.println("Double push");
      if(CharCase == Lowercase){
       CharCase = Uppercase;
      }
      else{
       CharCase = Lowercase;
      }
      break;
      
    case BfButton::LONG_PRESS:
      Serial.println("Long push");
      State = MainMenu;
      lcd.clear();
      display(Menu);
      TopMenu.back();
      break;
  }
}

void pressHandler2 (BfButton *btn, BfButton::press_pattern_t pattern) {
switch (pattern) {
    case BfButton::SINGLE_PRESS:
      Serial.println("Single");
        break;
    case BfButton::DOUBLE_PRESS:
      Serial.println("double");
        break;

    case BfButton::LONG_PRESS:
      Serial.println("long");  
        break;

}
}

void readRotar() {
  bool currentStateCLK = digitalRead(CLK);

  if (currentStateCLK != lastStateCLK && currentStateCLK == 1) {
    if (rotarDelay < sensitivity) {
      rotarDelay++;
    } else {
      rotarDelay = 0;

      if (digitalRead(DT) != currentStateCLK) {
        // Move right
        switch (State) {
          case MainMenu:
            TopMenu.down();
            break;
          case Write:
            charPos++;
            Serial.println(charPos);
            break;
          case Sensitivity:
            sensitivity++;
            Serial.println(sensitivity);
            lcd.setCursor(0, 0);
            lcd.println(sensitivity);
            //lpg.draw(sensitivity);
            break;
        }
      } else {
        // Move left
        switch (State) {
          case MainMenu:
            TopMenu.up();
            break;
          case Write:
            charPos--;
            Serial.println(charPos);
            break;
          case Sensitivity:
            sensitivity--;
            Serial.println(sensitivity);
            lcd.setCursor(0, 0);
            lcd.println(sensitivity);
            //lpg.draw(sensitivity);
            break;
        }
      }
    }
  }

  lastStateCLK = currentStateCLK;
}


void initLpg()
{
  lcd.println(sensitivity);
  lcd.setCursor(0,0);
  lpg.draw(sensitivity);
  Serial.println(sensitivity);
  //-- Set min and max values
  //-- Draw it: the frame
  
}

void drawPgsBar()
{
initLpg();
lpg.draw(sensitivity);
while(State == Sensitivity)
  {
      lpg.draw(sensitivity);
      btn.read(); 
      readRotar();
      //if(!sensitivity){break;}
      //-- draw progress bar
      if (sensitivity > 8) 
      {
         //---  Duration's over: delay and start again!
        sensitivity = 0;
          Serial.println(sensitivity);
          lcd.setCursor(0,0);
          lcd.println(sensitivity);
          lpg.draw(sensitivity);
          initLpg();
      }
      else if(sensitivity < 0)
      {
         sensitivity = 8;
         Serial.println(sensitivity);
          lcd.setCursor(0,0);
          lcd.println(sensitivity);
          lpg.draw(sensitivity);
      }
  }
}

void display(SimpleMenu *_menu)
{
  if(State == MainMenu)
  {
  lcd.clear();
  lcd.print(">");
  lcd.print(_menu->name);

  SimpleMenu *next = TopMenu.next();
  if(next != NULL)
  {
    lcd.setCursor(1,1);
    lcd.print(next->name);
  }
}
}

void writeMode(){
if(State != Write){
    State = Write;
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.println(userText);
    lcd.setCursor(cursorPos, 0);
  }
   if(State == Write){
      readRotar();
      btn.read(); 
     if (charPos < 0 ) {
       charPos = alphabetSize - 1;
     }
    else if (charPos >= alphabetSize + 1) {
        charPos = 0;
      }
    switch(CharCase){
    case Uppercase:
      lcd.print(upperCase[charPos]);
      break;
    case Lowercase:
      lcd.print(lowerCase[charPos]);
      break;
  }
  lcd.setCursor(cursorPos, 0);
}
}

void Credits(){
  lcd.setCursor(0,0);
  lcd.println("Created by me");
  delay(5000);
  lcd.clear();
  lcd.println("thanks to google");
  delay(5000);
  lcd.clear();
  lcd.println("and study lesson");
  lcd.setCursor(0,1);
  lcd.print("for distracting");
  delay(5000);
  lcd.clear();
}

void loop() {
  switch(State)
  {
    case MainMenu:
      readRotar();
      btn.read();  
      break;
    case Write: 
      writeMode();
      btn2.read();
      break;
  }
}