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

// Connect rotary pins to the DIGITAL or ANALOG pins of the Arduino board
// Use A0..A7 when using analog pins
#define ROTARY2_PIN1        5
#define ROTARY2_PIN2        4
#define ROTARY2_BUTTON_PIN  6
#define ROTARY1_PIN1        2
#define ROTARY1_PIN2        3
#define ROTARY1_BUTTON_PIN  13
#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 charPos = 0;
int cursorPosX = 0;
int cursorPosY = 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];
BfButton btn2(BfButton::STANDALONE_DIGITAL, ROTARY2_BUTTON_PIN, true, LOW);
BfButton btn(BfButton::STANDALONE_DIGITAL, ROTARY1_BUTTON_PIN, true, LOW);
// Configure a number of rotaries
#define NUM_ROTARIES        2

// Initialize full step rotary encoder with internal pull-up pins enabled
// and default sensitivity=100
RotaryFullStep rotaries[NUM_ROTARIES] = {
    RotaryFullStep(ROTARY1_PIN1, ROTARY1_PIN2),
    RotaryFullStep(ROTARY2_PIN1, ROTARY2_PIN2)
};

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();
}

// Global variables
int pinStateLast[NUM_ROTARIES];

// Forward declarations


void setup()
{
    // Initialize Serial port
  Serial.begin(115200);
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  //lcd.println("Wordman 1.0");
  //lcd.setCursor(0,1);
  //lcd.print("lcd edition");
  //delay(1500);
  lpg.setMinValue(0);
  lpg.setMaxValue(8);
  lcd.clear();
    for (int i = 0; i < alphabetSize; i++) {
        lowerCase[i] = 'a' + i;
    }
        for (int i = 0; i < alphabetSize; i++) {
        upperCase[i] = 'A' + i;
    }
  TopMenu.begin(display);
 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
}

void pressHandler (BfButton *btn, 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;
            }
          cursorPosX++;
          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 *btn2, BfButton::press_pattern_t pattern) {
  switch (pattern) {
    case BfButton::SINGLE_PRESS:
      Serial.println("delete char");
      break;
      
    case BfButton::DOUBLE_PRESS:
      Serial.println("character special case toggle probably");
      break;
      
    case BfButton::LONG_PRESS:
      Serial.println("multi delete possibly");
      break;
  }
}
void readRotar()
{
for (uint8_t i = 0; i < NUM_ROTARIES; i++) {
        // Read rotary state
        int rotaryState = rotaries[i].read();
        //When rotar is turned right
        if ((rotaryState < 0)) {
            //Rotar 1
            if(i==0)
            {
              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
            //rotar 2
            {
              if(State == Write)
            {
              Serial.println("cursor forward");
              lcd.print(" ");
              userText += " ";
              cursorPosX++;
              Serial.println(cursorPosX);
              Serial.println(cursorPosY);
            }
            }
        }
        //When rotar is turned left
        else if(rotaryState > 0)
        {
          //rotar 1
          if(i==0)
          {
            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;
              }
          }
          //rotar 2
          else
          {
            if(State == Write && cursorPosX >= 0)
            {
              
              //else{
              Serial.println("cursor back");
              lcd.print(" ");
              cursorPosX--;
              Serial.println(cursorPosX);
              Serial.println(cursorPosY);
              userText.remove(userText.length()-1);
            //}
            }
          }
        }
    }
}

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(cursorPosX, cursorPosY);
    Serial.println(State);
  }
  if(State == Write){
    readRotar();
    btn.read(); 
    btn2.read();

      if(cursorPosX > 15 && cursorPosY >= 0)
      {
        Serial.println("autoscroll down");
        cursorPosX = 0;
        cursorPosY++;
        Serial.println(cursorPosX);
        Serial.println(cursorPosY);
        lcd.setCursor(cursorPosX, cursorPosY);
      }

      if(cursorPosX < 0 && cursorPosY >= 1)
      {
        Serial.println("autoscroll up");
        cursorPosX = 15;
        cursorPosY--;
        Serial.println(cursorPosX);
        Serial.println(cursorPosY);
        lcd.setCursor(cursorPosX, cursorPosY);
      }

    if (charPos < 0) {
      charPos = alphabetSize - 1;
      Serial.println(lowerCase[charPos]);
    }
    else if (charPos > alphabetSize - 1) {
      charPos = 0;
      Serial.println(lowerCase[charPos]);
    }
    switch(CharCase){
    case Uppercase:
      lcd.print(upperCase[charPos]);
      break;
    case Lowercase:
      lcd.println(lowerCase[charPos]);
      break;
    }
    lcd.setCursor(cursorPosX, cursorPosY);
  }
}

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();
      break;
  }
}