//Joystick button codes
#define JOYSTICK_UP 1
#define JOYSTICK_CENTER 2
#define JOYSTICK_LEFT 3
#define JOYSTICK_DOWN 4
#define JOYSTICK_RIGHT 5
//IR remote button codes 
#define IRButton_1 1
#define IRButton_2 2
#define IRButton_3 3
#define IRButton_4 4
#define IRButton_5 5
#define IRButton_6 6
#define IRButton_7 7
#define IRButton_8 8
#define IRButton_9 9
#define IRButton_STAR 10 //*
#define IRButton_0 11 
#define IRButton_SHARP 12 //#
#define IRButton_UP 13
#define IRButton_LEFT 14 
#define IRButton_OK 15 
#define IRButton_RIGHT 16 
#define IRButton_DOWN 17 

extern Calendar now;

const String settingItemsLabel[] = {
  "Change date",
  "Change time",
  "Setup alarm",
  "Disable alarm",
  "Back"
};

uint8_t menuOffset;
bool isCursorUp;
int8_t activeItemIndex;

AppState SettingsScreen(LiquidCrystal_I2C* lcd, AppState prevAppState){
  //Init
  if(prevAppState != APPSTATE_SETTINGS){
    lcd->clear();

    menuOffset = 0;
    isCursorUp = true;
    activeItemIndex = -1;

    lcd->home();
    lcd->print(">");
    lcd->print(settingItemsLabel[0]);
    lcd->setCursor(1, 1);
    lcd->print(settingItemsLabel[1]);
  }

  //Proccess active menu item
  if(activeItemIndex != -1){
    switch(activeItemIndex){
      case 0:
        SettingsScreen_EditDate(lcd);
        break;
      case 1:
        SettingsScreen_EditTime(lcd);
        break;
      case 2:
        SettingsScreen_SetupAlarm(lcd);
        break;
      case 3:
        SettingsScreen_DisableAlarm(lcd);
        break;
      case 4:
        return APPSTATE_DISPLAY;
        break;
    }

    return APPSTATE_SETTINGS;
  }

  //Handle button "Down" click
  if((Joystick_isButtonPressed(JOYSTICK_DOWN) || IR_isButtonPressed(IRButton_DOWN)) && !(menuOffset == 3 && !isCursorUp)){
    if(isCursorUp){
      isCursorUp = false;
      lcd->setCursor(0, 0);
      lcd->print(" ");
      lcd->setCursor(0, 1);
      lcd->print(">");
    } else {
      menuOffset++;
      
      lcd->clear();
      lcd->home();

      lcd->print(" ");
      lcd->print(settingItemsLabel[menuOffset]);
      lcd->setCursor(0, 1);
      lcd->print(">");
      lcd->print(settingItemsLabel[1+menuOffset]);
    }
  }
  //Handle button "Up" click
  if((Joystick_isButtonPressed(JOYSTICK_UP) || IR_isButtonPressed(IRButton_UP)) && !(menuOffset == 0 && isCursorUp)){
    if(!isCursorUp){
      isCursorUp = true;
      lcd->setCursor(0, 0);
      lcd->print(">");
      lcd->setCursor(0, 1);
      lcd->print(" ");
    } else {
      menuOffset--;
      
      lcd->clear();
      lcd->home();
      
      lcd->print(">");
      lcd->print(settingItemsLabel[menuOffset]);
      lcd->setCursor(0, 1);
      lcd->print(" ");
      lcd->print(settingItemsLabel[1+menuOffset]);
    }
  }

  //Handle button "Ok/Center" click
  if(Joystick_isButtonPressed(JOYSTICK_CENTER) || IR_isButtonPressed(IRButton_OK)){
    activeItemIndex = menuOffset + 1-(int)isCursorUp;
  }

  return APPSTATE_SETTINGS;
} 

void SettingsScreen_EditDate(LiquidCrystal_I2C* lcd){
  static bool hasBeenInit = false;

  static uint8_t day, month;
  static uint16_t year;
  static uint8_t index;
  static uint32_t timer;
  
  if(!hasBeenInit){
    day = 0; month = 0; year = 0;
    index = 0;

    lcd->setCursor(0, 1-isCursorUp);
    lcd->print(">Date __.__.____");
    lcd->setCursor(6, 1-isCursorUp);
    lcd->blink();

    hasBeenInit = true;
  }

  int8_t pressedDigit = IR_isDigitPressed();
  if(pressedDigit != -1){
    lcd->print(pressedDigit);
    
    switch(index){
      case 0:
        day += pressedDigit*10;
        index=1;
        break;
      case 1:
        day += pressedDigit;
        index=3;
        break;

      case 3: 
        month += pressedDigit*10;
        index=4;
        break;
      case 4:
        month += pressedDigit;
        index=6;
        break;

      case 6:
        year += pressedDigit*1000;
        index=7;
        break;
      case 7:
        year += pressedDigit*100;
        index=8;
        break;
      case 8:
        year += pressedDigit*10;
        index=9;
        break;
      case 9:
        year += pressedDigit;
        index=10;
        break;
    }

    lcd->setCursor(6+index, 1-isCursorUp);

    if(index == 10){
      bool success = Calendar_EditDate(day, month, year);
      lcd->noBlink();
      lcd->setCursor(0, 1-isCursorUp);
      if(success) lcd->print("Date changed    ");
      else lcd->print("Date not changed");
    
      timer = millis() + 1000;
    }
  }
  
  if(index == 10 && millis() > timer){
    lcd->setCursor(0, 1-isCursorUp);
    lcd->print(">Change date     ");

    activeItemIndex = -1;
    hasBeenInit = false;
  }
}

void SettingsScreen_EditTime(LiquidCrystal_I2C* lcd){
  static bool hasBeenInit = false;

  static uint8_t hour, minute, second;
  static uint8_t index;
  static uint32_t timer;
  
  if(!hasBeenInit){
    hour = 0; minute = 0; second = 0;
    index = 0;

    lcd->setCursor(0, 1-isCursorUp);
    lcd->print(">Time __:__:__   ");
    lcd->setCursor(6, 1-isCursorUp);
    lcd->blink();

    hasBeenInit = true;
  }

  int8_t pressedDigit = IR_isDigitPressed();
  if(pressedDigit != -1){
    lcd->print(pressedDigit);
    
    switch(index){
      case 0:
        hour += pressedDigit*10;
        index=1;
        break;
      case 1:
        hour += pressedDigit;
        index=3;
        break;

      case 3: 
        minute += pressedDigit*10;
        index=4;
        break;
      case 4:
        minute += pressedDigit;
        index=6;
        break;

      case 6:
        second += pressedDigit*10;
        index=7;
        break;
      case 7:
        second += pressedDigit;
        index=8;
        break;
    }

    lcd->setCursor(6+index, 1-isCursorUp);

   if(index == 8){
      bool success = Calendar_EditTime(hour, minute, second);
      lcd->noBlink();
      lcd->setCursor(0, 1-isCursorUp);
      if(success) lcd->print("Time changed    ");
      else lcd->print("Time not changed");
    
      timer = millis() + 1000;
    }
  }

  if(index == 8 && millis() > timer){
    lcd->setCursor(0, 1-isCursorUp);
    lcd->print(">Change time     ");

    activeItemIndex = -1;
    hasBeenInit = false;
  }
}

void SettingsScreen_SetupAlarm(LiquidCrystal_I2C* lcd){
  static bool hasBeenInit = false;

  static uint8_t hour, minute, second;
  static uint8_t index;
  static uint32_t timer;
  
  if(!hasBeenInit){
    hour = 0; minute = 0; second = 0;
    index = 0;

    lcd->setCursor(0, 1-isCursorUp);
    lcd->print(">Alarm __:__:__  ");
    lcd->setCursor(7, 1-isCursorUp);
    lcd->blink();

    hasBeenInit = true;
  }

  int8_t pressedDigit = IR_isDigitPressed();
  if(pressedDigit != -1){
    lcd->print(pressedDigit);
    
    switch(index){
      case 0:
        hour += pressedDigit*10;
        index=1;
        break;
      case 1:
        hour += pressedDigit;
        index=3;
        break;

      case 3: 
        minute += pressedDigit*10;
        index=4;
        break;
      case 4:
        minute += pressedDigit;
        index=6;
        break;

      case 6:
        second += pressedDigit*10;
        index=7;
        break;
      case 7:
        second += pressedDigit;
        index=8;
        break;
    }

    lcd->setCursor(7+index, 1-isCursorUp);

   if(index == 8){
      bool success = Calendar_SetupAlarm(hour, minute, second);
      lcd->noBlink();
      lcd->setCursor(0, 1-isCursorUp);
      if(success) lcd->print("Alarm setup     ");
      else lcd->print("Alarm not setup ");
    
      timer = millis() + 1000;
    }
  }

  if(index == 8 && millis() > timer){
    lcd->setCursor(0, 1-isCursorUp);
    lcd->print(">Setup alarm     ");

    activeItemIndex = -1;
    hasBeenInit = false;
  }
}

void SettingsScreen_DisableAlarm(LiquidCrystal_I2C* lcd){
  static bool hasBeenInit = false;

  static uint32_t timer;
  
  if(!hasBeenInit){
    Calendar_DisableAlarm();

    lcd->setCursor(0, 1-isCursorUp);
    lcd->print("Alarm disabled  ");

    timer = millis() + 1000;
    hasBeenInit = true;
  }

  if(millis() > timer){
    lcd->setCursor(0, 1-isCursorUp);
    lcd->print(">Disable alarm   ");

    activeItemIndex = -1;
    hasBeenInit = false;
  }

}

