//Handle main app routine
//........................
//#include "ButtonRotaryHandler.h"
//#include "MenuHandler.h"
//#include "DisplayHandler.h"

#define MENU_NONE 0
#define MENU_DASHBOARD 1
#define MENU_SELECT_OPTION 2
#define MENU_DURATION_MAIN 3
#define MENU_DURATION_POST_UV 4
#define MENU_CONNECTION 5
#define MENU_ABOUT 6

#define SUBMENU_SELECT_NONE 0

int8_t displayIdx = MENU_NONE;
int8_t menuIdx = 0;
int8_t menuDisplayLowerBound = 0;
int8_t menuDisplayUpperBound = 0;

uint32_t waitDelay = 0;
uint32_t waitTick = 0;
bool responseCleanupButton = false;
bool responseCleanupRotary = false;

const char* textStartStop[] = {
  "Mulai Sterilisasi", 
  "Stop Sterilisasi"
};

const char* textStartStopRefill[] = {
  "Mulai Refill", 
  "Stop Refill"
};

const char* textAutoMode[] = {
  "Otomasi Steril: Ya", 
  "Otomasi Steril: Tidak"
};

const char* textAutoRefillMode[] = {
  "Otomasi Refill: Ya", 
  "Otomasi Refill: Tidak"
};

const char* menus[] = {
  "Mulai/Stop Sterilisasi",
  "Mulai/Stop Refill",
  "Otomasi Steril: Ya/Tidak",
  "Otomasi Refill: Ya/Tidak",
  "Durasi Sterilisasi",
  "Post-Sterilisasi UV",
  "Koneksi",
  "Tentang Aplikasi",
  "Kembali"
};

#define SUBMENU_START_STOP 0
#define SUBMENU_START_STOP_REFILL 1
#define SUBMENU_AUTOMODE 2
#define SUBMENU_AUTOMODE_REFILL 3
#define SUBMENU_DURATION 4
#define SUBMENU_POST_UV 5
#define SUBMENU_CONNECTION 6
#define SUBMENU_ABOUT 7
#define SUBMENU_BACK 8

const char* durationSelect[] = {
  "5 Menit", 
  "10 Menit",
  "15 Menit",
  "20 Menit",
  "25 Menit",
  "30 Menit"
};

const char* durationSelect2[] = {
  "Non-Aktifan", 
  "5 Menit",
  "10 Menit",
  "15 Menit",
  "20 Menit",
  "25 Menit",
  "30 Menit"
};

const char* apSelect2[] = {
  "Kembali", 
  "Aktifkan/Nonaktifkan",
  "Password Baru"
  "Tanpa Password"
};

int dialogSelectionIndex = 0;

int SelectDialog(const char *title, const char *text, const char* durationList[], int indexLimit){
  //limit index
  if (dialogSelectionIndex>indexLimit) dialogSelectionIndex = indexLimit;
  if (dialogSelectionIndex<0) dialogSelectionIndex = 0;

  if (ButtonSwitchedEvent()==BUTTON_UNPRESSED_EVENT){
    Serial.println("OK");
    return dialogSelectionIndex;
  }

  int direction = RotaryEvent();
  if (direction==DIRECTION_CW){
    dialogSelectionIndex++;
    if (dialogSelectionIndex>indexLimit) dialogSelectionIndex = indexLimit;
    Serial.println(">>");
  }else if (direction==DIRECTION_CCW){
    dialogSelectionIndex--;
    if (dialogSelectionIndex<0) dialogSelectionIndex = 0;
    Serial.println("<<");
  }
  
  ClearDisplayBuffer();
  DrawCenteredText(title, 0, false, false, false, true);
  DrawCenteredText(text, 2, false);
  //DrawCenteredText("30 Menit", 3, true, true, true);
  DrawCenteredText(durationList[dialogSelectionIndex], 3, true, (dialogSelectionIndex>0), (dialogSelectionIndex<indexLimit));
  SendDisplayBuffer();
  
  return -1;
}

void SetWaitResponse(uint32_t delayMillis, bool needButtonCleanup=false, bool needRotaryCleanup = false){
  waitDelay = delayMillis;
  waitTick = millis();
  responseCleanupButton = needButtonCleanup;
  responseCleanupRotary = needRotaryCleanup;
}

void AppStartSterilizationSystem(){
  Serial.println("AppStartSterilizationSystem()");
  //copy configuration and start
  bool useUV = GetPostUVTimeIndex()>0;
  uint32_t uvDuration = ((uint32_t)GetPostUVTimeIndex()) * (5 * 60 * 1000);
  ChamberSetPostUvDuration(uvDuration);
  uint32_t ozoneDuration = ((uint32_t) (1+GetSterilizationTimeIndex())) * (5 * 60 * 1000);
  //uint32_t ozoneDuration = ((uint32_t) (1+GetSterilizationTimeIndex())) * (1 * 60 * 1000);
  ChamberSetSterlizationDuration(ozoneDuration);
  bool autoMode = GetSettingAutoMode();
  StartChamberSystem(autoMode, true, useUV);
}

void AppStartRefillSystem(){
  Serial.println("AppStartRefillSystem()");
  //copy configuration and start
  StartWaterBankSystem(GetSettingAutoRefillMode(), true);
}

//handle app logic
void AppRoutine(){

  //background task
  //..................
  
  if ((millis()-waitTick)<waitDelay){
    if (responseCleanupButton) ButtonResetEvent();
    if (responseCleanupRotary) RotaryResetEvent();
    return;
  }else{
    if (responseCleanupButton) {
      responseCleanupButton = false;
      ButtonResetEvent();
    }
    if (responseCleanupRotary) {
      responseCleanupRotary = false;
      RotaryResetEvent();
    }
  }
  
  switch (displayIdx){
    case MENU_NONE:{
      SetWaitResponse(2000, true, true);
      displayIdx = MENU_DASHBOARD;
      SplashScreen();
      //u8g2.setPowerSave(1); //not working :(
      Serial.println("Switch: MENU_DASHBOARD");
      return;
    }
    break;
    case MENU_DASHBOARD:{
      
      //DashboardDemoRoutine();
      DashboardRoutine();
      
      //handle button to enter select option
      if (ButtonSwitchedEvent()==BUTTON_UNPRESSED_EVENT){
        displayIdx = MENU_SELECT_OPTION;
        menuIdx = 0;
        menuDisplayLowerBound = 0;
        int maxMenuCount = sizeof(menus) / sizeof(menus[0]);;
        menuDisplayUpperBound = min(DrawTextRowCount(), maxMenuCount)-1;
        Serial.print("Menu upper bound: ");
        Serial.println(menuDisplayUpperBound);
        Serial.println("Switch: MENU_SELECT_OPTION");
        SetWaitResponse(50, true, true);
      }else{
        SetWaitResponse(5, false, false);
      }
    }
    break;
    case MENU_SELECT_OPTION:{
      //handle rotary
      int maxDisplayTextRow = DrawTextRowCount();
      int maxMenuCount = sizeof(menus) / sizeof(menus[0]);
      int boundDiff = (min(DrawTextRowCount(), maxMenuCount)-1);
      int direction = RotaryEvent();
      bool rotaryChanged = false;
      if (direction==DIRECTION_CW){
        rotaryChanged = true;
        menuIdx++;
        if (menuIdx>=maxMenuCount){
          menuIdx = 0;
          menuDisplayLowerBound = 0;
          menuDisplayUpperBound = boundDiff;
        }
        if (menuIdx>menuDisplayUpperBound){
          menuDisplayUpperBound = menuIdx;
          menuDisplayLowerBound = menuDisplayUpperBound-boundDiff;
        }
      }else if (direction==DIRECTION_CCW){
        Serial.println("handle CCW");
        rotaryChanged = true;
        menuIdx--;
        if (menuIdx<0){
          menuIdx=maxMenuCount-1;
          menuDisplayUpperBound = menuIdx;
          menuDisplayLowerBound = menuDisplayUpperBound-boundDiff;          
        }
        //Serial.print("lowerbound "); Serial.println(menuDisplayLowerBound);
        //Serial.print("upperbound "); Serial.println(menuDisplayUpperBound);
        
//        if (menuDisplayUpperBound<menuIdx){
//          menuDisplayUpperBound = menuIdx;
//          menuDisplayLowerBound = menuDisplayUpperBound-boundDiff;
//        }
        
        if (menuIdx<menuDisplayLowerBound){
          menuDisplayLowerBound = menuIdx;
          menuDisplayUpperBound = menuDisplayLowerBound+boundDiff;
          if (menuDisplayUpperBound>=maxMenuCount) menuDisplayUpperBound = maxMenuCount-1;
        }
      }

      if (rotaryChanged){
        SetWaitResponse(50);//next response is 50 (best)
      }
      
      //handle button
      if (ButtonSwitchedEvent()==BUTTON_UNPRESSED_EVENT){
        Serial.print("Clicking sub menu: ");
        Serial.println(menuIdx);
        switch(menuIdx){
          case SUBMENU_START_STOP:{
            if (IsChamberSystemRunning()){
              Serial.println("Call: StopChamberSystem()");
              StopChamberSystem();
            }else{
              Serial.println("Call: AppStartSterilizationSystem()");
              ClearWaterBankError();//clear error juga buat water tank
              AppStartSterilizationSystem();
            }
            displayIdx = MENU_DASHBOARD;
            Serial.println("Switch: MENU_DASHBOARD");
            SetWaitResponse(0, true, true);
            return;
          };
          case SUBMENU_START_STOP_REFILL:{
            if (IsWaterBankSystemRunning()){
              StopWaterBankSystem();
            }else{
              ClearChamberError();//clear error juga buat chamber
              AppStartRefillSystem();
            }
            displayIdx = MENU_DASHBOARD;
            Serial.println("Switch: MENU_DASHBOARD");
            SetWaitResponse(0, true, true);
            return;
          };
          break;
          case SUBMENU_AUTOMODE:{
            SetSettingAutoMode(!GetSettingAutoMode());
            SetWaitResponse(0, true, true);
            return;
          };
          break;
          case SUBMENU_AUTOMODE_REFILL:{
            SetSettingAutoRefillMode(!GetSettingAutoRefillMode());
            SetWaitResponse(0, true, true);
            return;
          };
          break;
          case SUBMENU_DURATION:{
            dialogSelectionIndex = GetSterilizationTimeIndex();
            displayIdx = MENU_DURATION_MAIN;
            Serial.println("Switch: MENU_DURATION_MAIN");
            SetWaitResponse(0, true, true);
            return;
          };
          break;
          case SUBMENU_POST_UV:{
            dialogSelectionIndex = GetUVTimeIndex();
            displayIdx = MENU_DURATION_POST_UV;
            Serial.println("Switch: MENU_DURATION_POST_UV");
            SetWaitResponse(0, true, true);
            return;
          };
          break;
          case SUBMENU_CONNECTION:{
            displayIdx = MENU_CONNECTION;
            Serial.println("Switch: MENU_CONNECTION");
            SetWaitResponse(0, true, true);
            return;
          };
          break;
          case SUBMENU_ABOUT:{
            displayIdx = MENU_ABOUT;
            Serial.println("Switch: MENU_ABOUT");
            SetWaitResponse(0, true, true);
            return;
          };
          break;
          case SUBMENU_BACK:{
            displayIdx = MENU_DASHBOARD;
            Serial.println("Switch: MENU_DASHBOARD");
            SetWaitResponse(200, true, true);
            return;
          };
          break;
        }
      }
      
      //adapt state
      if (!IsChamberSystemRunning()){
        menus[SUBMENU_START_STOP] = textStartStop[0];
      }else{
        menus[SUBMENU_START_STOP] = textStartStop[1];
      }
      //adapt state for refill
      if (!IsWaterBankSystemRunning()){
        menus[SUBMENU_START_STOP_REFILL] = textStartStopRefill[0];
      }else{
        menus[SUBMENU_START_STOP_REFILL] = textStartStopRefill[1];
      }
      //adapt sterilization auto mode text:
      if (GetSettingAutoRefillMode()){
        menus[SUBMENU_AUTOMODE_REFILL] = textAutoRefillMode[0];
      }else{
        menus[SUBMENU_AUTOMODE_REFILL] = textAutoRefillMode[1];
      }
      //adapt refill auto mode text:
      if (GetSettingAutoMode()){
        menus[SUBMENU_AUTOMODE] = textAutoMode[0];
      }else{
        menus[SUBMENU_AUTOMODE] = textAutoMode[1];
      }
      ClearDisplayBuffer();
      //DrawSectionPlaceholder();
      int pointerIdx = menuIdx;
      int row = 0;
      for (int i=menuDisplayLowerBound;i<=menuDisplayUpperBound;i++){
        DrawTextMenuAtRow(menus[i], row, i==pointerIdx);
        row++;
      }
      SendDisplayBuffer();
    }
    break;
    case MENU_DURATION_MAIN:{
      int idx = SelectDialog("Durasi Sterilisasi", "Pilihan Durasi:", durationSelect, 5);
      if (idx>=0){
        displayIdx = MENU_SELECT_OPTION;
        SetSterilizationTimeIndex(idx);
        SetWaitResponse(0, true, true);
      }else{
        SetWaitResponse(50, false, false);
      }
    }
    break;
    case MENU_DURATION_POST_UV:{
      int limit = 6;
      int idx = SelectDialog("Post-Sterilisasi UV", "Pilihan Durasi:", durationSelect2, limit);
      if (idx>=0){
        displayIdx = MENU_SELECT_OPTION;
        SetPostUVTimeIndex(idx);
        SetWaitResponse(0, true, true);
      }else{
        SetWaitResponse(50, false, false);
      }
    }
    break;
    case MENU_CONNECTION:{
      //DrawUnderConstruction();
      ClearDisplayBuffer();
      DrawCenteredText("Koneksi", 0, false, false, false, true);
      DrawCenteredText("SSID: HYDROZONER_V1", 1, false);
      String pwd = "Password: " + GetApPassword();
      DrawCenteredText(pwd.c_str(), 2, false);
      SendDisplayBuffer();
      displayIdx = MENU_SELECT_OPTION;
      SetWaitResponse(5000, true, true);
    }
    break;
    case MENU_ABOUT:{
      DrawAbout();
      if (ButtonSwitchedEvent()==BUTTON_UNPRESSED_EVENT){
        displayIdx = MENU_SELECT_OPTION;
      }
    }
    break;
  }
}

void InitApp(){
  //cek setingan kalau mode auto maka dijalankan
  if (GetSettingAutoMode()){
    AppStartSterilizationSystem();
  }

  if (GetSettingAutoRefillMode()){
    AppStartRefillSystem();
  }
}
