#include <LiquidCrystal_I2C.h>
#include <mechButton.h>

#define BLINK_MS  500 // Defualt.

class autoLCD :  public LiquidCrystal_I2C,
                public idler,
                public timeObj {

  public:
          autoLCD(int addr,int width,int height);
  virtual ~autoLCD(void);

          void  showCursor(bool onOff);
  virtual void  idle();

          bool  cursorOn;
          bool  usingCursor;
};


autoLCD::autoLCD(int addr,int width,int height) 
  : LiquidCrystal_I2C(addr,width,height),
  idler(),
  timeObj(BLINK_MS) {
    
    usingCursor = false;
    cursorOn      = false;
  }


autoLCD::~autoLCD(void) {  }


void  autoLCD::showCursor(bool onOff) {

  hookup();
  if (onOff) {
    cursor();
    start();
  } else {
    noCursor();
    reset();
  }
  usingCursor = onOff;
}


void  autoLCD::idle() {

  if (usingCursor) {
    if (ding()) {
      cursorOn = !cursorOn;
      if (cursorOn) {
        cursor();
      } else {
        noCursor();
      }
      stepTime();
    }
  }
}


autoLCD lcd(0x27,16,2);
char    sourceStr[17];
char    editStr[17];
int     cursorX;
int     numChars;
mechButton  fwdBtn(2);
mechButton  backBtn(4);
mechButton  selectBtn(3);
mechButton  deleteBtn(5);

void setup(void) {

  Serial.begin(115200);\
  strcpy(sourceStr,"  Hello world.  ");
  strcpy(editStr,"");
  fwdBtn.setCallback(clickUp);
  backBtn.setCallback(clickDn);
  selectBtn.setCallback(clickChoose);
  deleteBtn.setCallback(clickDelete);
  lcd.init();                         // initialize the lcd
  lcd.backlight();                    // Do the backlight thing.
  lcd.clear();                        // Clean up screen.
  lcd.setCursor(0,0);                 // Move cursor position.
  lcd.print(sourceStr);               // Spit out message at cursor position.
  setCursor(0);                       // Get ready for choosing.
  lcd.showCursor(true);
}


void setCursor(int xPos) {

  if (xPos<0) cursorX = 0;
  else if (xPos>15) cursorX = 16;
  else cursorX = xPos;
  lcd.setCursor(cursorX,0);                 // Move cursor position.
}


void returnCursor(void) {
  
  lcd.setCursor(cursorX,0);
}


void showEdit(void) {

  lcd.noCursor();
  lcd.setCursor(0,1);
  lcd.print("                ");
  lcd.setCursor(0,1);
  lcd.print(editStr);
  returnCursor();
}


void clickUp(void) {

  if (!fwdBtn.getState()) {
    cursorX++;
    if (cursorX>16) cursorX=16;
  }
  lcd.setCursor(cursorX,0);
}


void clickDn(void) {

  if (!backBtn.getState()) {
    cursorX--;
    if (cursorX<0) cursorX=0;
  }
  lcd.setCursor(cursorX,0);
}

void clickChoose(void) {

  char buff[2];

  if (!selectBtn.getState()) {
    buff[0] = sourceStr[cursorX];
    buff[1] = '\0';
    strcat(editStr,buff);
    showEdit();
  }
}


void clickDelete(void) {

  if (!deleteBtn.getState()) {
    if (strlen(editStr)>0) {
      editStr[strlen(editStr)-1]='\0';
      showEdit();
    }
  }
}


void loop() { idle(); }