// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "minios/screens.h"

#include <algorithm>
#include <utility>

#include <base/json/json_reader.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>

#include "minios/minios.h"

namespace screens {

const char kScreens[] = "etc/screens";

// Colors.
const char kMenuDropdownFrameNavy[] = "0x435066";
const char kMenuDropdownBackgroundBlack[] = "0x2D2E30";

// Key values.
const int kKeyUp = 103;
const int kKeyDown = 108;
const int kKeyEnter = 28;
const int kKeyVolUp = 115;
const int kKeyVolDown = 114;
const int kKeyPower = 116;

// Key state parameters.
const int kFdsMax = 10;
const int kKeyMax = 200;

namespace {
// Buttons Spacing
constexpr int kTitleY = (-1080 / 2) + 238;
constexpr int kBtnYStep = 40;

// Dropdown size.
constexpr int kNetworksPerPage = 10;
}  // namespace

bool Screens::Init() {
  CheckDetachable();
  CheckRightToLeft();
  GetVpdRegion();
  ReadHardwareId();

  screens_path_ = root_.Append(kScreens);
  // TODO(vyshu): Change constants.sh and lang_constants.sh to simple text file.
  ReadDimensionConstants();
  ReadLangConstants();

  std::vector<int> wait_keys;
  if (!is_detachable_)
    wait_keys = {kKeyUp, kKeyDown, kKeyEnter};
  else
    wait_keys = {kKeyVolDown, kKeyVolUp, kKeyPower};
  if (!key_reader_.Init(wait_keys)) {
    LOG(ERROR) << "Could not initialize key reader. Unable to continue. ";
    return false;
  }
  return true;
}

bool Screens::InitForTest() {
  screens_path_ = root_.Append(kScreens);
  ReadDimensionConstants();
  return true;
}

void Screens::StartMiniOsFlow() {
  index_ = 1;
  return ShowMiniOsWelcomeScreen();
}

void Screens::ShowLanguageDropdown() {
  constexpr int kItemHeight = 40;
  const int kItemPerPage = (frecon_canvas_size_ - 260) / kItemHeight;

  // Pick begin index such that the selected index is centered on the screen if
  // possible.
  int begin_index =
      std::clamp(index_ - kItemPerPage / 2, 0,
                 static_cast<int>(supported_locales_.size()) - kItemPerPage);

  int offset_y = -frecon_canvas_size_ / 2 + 88;
  const int kBackgroundX = -frecon_canvas_size_ / 2 + 360;
  for (int i = begin_index;
       i < (begin_index + kItemPerPage) && i < supported_locales_.size(); i++) {
    // Get placement for the language image.
    int language_width;
    if (!GetLangConstants(supported_locales_[i], &language_width)) {
      language_width = 95;
      LOG(WARNING) << "Could not get width for " << supported_locales_[i]
                   << ". Defaulting to " << language_width;
    }
    int lang_x = -frecon_canvas_size_ / 2 + language_width / 2 + 40;

    // This is the currently selected language. Show in blue.
    if (index_ == i) {
      ShowBox(kBackgroundX, offset_y, 720, 40, kMenuBlue);
      ShowImage(screens_path_.Append(supported_locales_[i])
                    .Append("language_focused.png"),
                lang_x, offset_y);
    } else {
      ShowBox(kBackgroundX, offset_y, 720, 40, kMenuDropdownFrameNavy);
      ShowBox(kBackgroundX, offset_y, 718, 38, kMenuDropdownBackgroundBlack);
      ShowImage(
          screens_path_.Append(supported_locales_[i]).Append("language.png"),
          lang_x, offset_y);
    }
    offset_y += kItemHeight;
  }
}

void Screens::LanguageMenuOnSelect() {
  ShowLanguageMenu(false);

  // Find index of current locale to show in the dropdown.
  index_ = std::distance(
      supported_locales_.begin(),
      std::find(supported_locales_.begin(), supported_locales_.end(), locale_));
  if (index_ == supported_locales_.size()) {
    // Default to en-US.
    index_ = 9;
    LOG(WARNING) << " Could not find an index to match current locale "
                 << locale_ << ". Defaulting to index " << index_ << " for  "
                 << supported_locales_[index_];
  }

  ShowLanguageDropdown();
}

void Screens::ShowLanguageMenu(bool is_selected) {
  const int kOffsetY = -frecon_canvas_size_ / 2 + 40;
  const int kBgX = -frecon_canvas_size_ / 2 + 145;
  const int kGlobeX = -frecon_canvas_size_ / 2 + 20;
  const int kArrowX = -frecon_canvas_size_ / 2 + 268;
  int language_width;
  if (!GetLangConstants(locale_, &language_width)) {
    language_width = 100;
    LOG(WARNING) << "Could not get language width for " << locale_
                 << ". Defaulting to 100.";
  }
  const int kTextX = -frecon_canvas_size_ / 2 + 40 + language_width / 2;

  base::FilePath menu_background =
      is_selected ? screens_path_.Append("language_menu_bg_focused.png")
                  : screens_path_.Append("language_menu_bg.png");

  ShowImage(menu_background, kBgX, kOffsetY);
  ShowImage(screens_path_.Append("ic_language-globe.png"), kGlobeX, kOffsetY);

  ShowImage(screens_path_.Append("ic_dropdown.png"), kArrowX, kOffsetY);
  ShowMessage("language_folded", kTextX, kOffsetY);
}

void Screens::ShowFooter() {
  constexpr int kQrCodeSize = 86;
  const int kQrCodeX = (-frecon_canvas_size_ / 2) + (kQrCodeSize / 2);
  const int kQrCodeY = (frecon_canvas_size_ / 2) - (kQrCodeSize / 2) - 56;

  const int kSeparatorX = 410 - (frecon_canvas_size_ / 2);
  const int kSeparatorY = kQrCodeY;
  constexpr int kFooterLineHeight = 18;

  const int kFooterY = (frecon_canvas_size_ / 2) - kQrCodeSize + 9 - 56;
  const int kFooterLeftX =
      kQrCodeX + (kQrCodeSize / 2) + 16 + (kDefaultMessageWidth / 2);
  const int kFooterRightX = kSeparatorX + 32 + (kDefaultMessageWidth / 2);

  ShowMessage("footer_left_1", kFooterLeftX, kFooterY);
  ShowMessage("footer_left_2", kFooterLeftX,
              kFooterY + kFooterLineHeight * 2 + 14);
  ShowMessage("footer_left_3", kFooterLeftX,
              kFooterY + kFooterLineHeight * 3 + 14);

  constexpr int kNavButtonHeight = 24;
  const int kNavButtonY =
      (frecon_canvas_size_ / 2) - (kNavButtonHeight / 2) - 56;
  int nav_btn_x = kSeparatorX + 32;
  // Navigation key icons.
  const std::string kFooterType = is_detachable_ ? "tablet" : "clamshell";
  const std::string kNavKeyEnter =
      is_detachable_ ? "button_power" : "key_enter";
  const std::string kNavKeyUp = is_detachable_ ? "button_volume_up" : "key_up";
  const std::string kNavKeyDown =
      is_detachable_ ? "button_volume_down" : "key_down";

  constexpr int kUpDownIconWidth = 24;
  constexpr int kIconPadding = 8;
  const int kEnterIconWidth = is_detachable_ ? 40 : 66;

  ShowMessage("footer_right_1_" + kFooterType, kFooterRightX, kFooterY);
  ShowMessage("footer_right_2_" + kFooterType, kFooterRightX,
              kFooterY + kFooterLineHeight + 8);

  nav_btn_x += kEnterIconWidth / 2;
  ShowImage(screens_path_.Append("nav-" + kNavKeyEnter + ".png"), nav_btn_x,
            kNavButtonY);
  nav_btn_x += kEnterIconWidth / 2 + kIconPadding + kUpDownIconWidth / 2;
  ShowImage(screens_path_.Append("nav-" + kNavKeyUp + ".png"), nav_btn_x,
            kNavButtonY);
  nav_btn_x += kIconPadding + kUpDownIconWidth;
  ShowImage(screens_path_.Append("nav-" + kNavKeyDown + ".png"), nav_btn_x,
            kNavButtonY);

  ShowImage(screens_path_.Append("qr_code.png"), kQrCodeX, kQrCodeY);
  int hwid_len = hwid_.size();
  int hwid_x = kQrCodeX + (kQrCodeSize / 2) + 16 + 5;
  const int kHwidY = kFooterY + kFooterLineHeight;

  if (right_to_left_) {
    hwid_x = -hwid_x - kMonospaceGlyphWidth * (hwid_len - 2);
  }

  ShowText(hwid_, hwid_x, kHwidY, "grey");
  ShowBox(kSeparatorX, kSeparatorY, 1, kQrCodeSize, kMenuGrey);
}

void Screens::MessageBaseScreen() {
  ClearMainArea();
  ShowLanguageMenu(false);
  ShowFooter();
}

void Screens::ShowMiniOsWelcomeScreen() {
  MessageBaseScreen();
  ShowInstructionsWithTitle("MiniOS_welcome");
  ShowStepper({"1", "2", "3"});

  ShowLanguageMenu(index_ == 0);
  constexpr int kBtnY = kTitleY + 80 + kBtnYStep * 2;
  ShowButton("btn_next", kBtnY, (index_ == 1), default_button_width_, false);
  ShowButton("btn_back", kBtnY + kBtnYStep, (index_ == 2),
             default_button_width_, false);
}

void Screens::ShowMiniOsNetworkDropdownScreen() {
  MessageBaseScreen();
  ShowInstructions("title_MiniOS_dropdown");
  ShowStepper({"1-done", "2", "3"});
  ShowLanguageMenu(index_ == 0);
  ShowCollapsedNetworkDropDown((index_ == 1));
  ShowButton("btn_back", kTitleY + 58 + (4 * kBtnYStep), (index_ == 2),
             default_button_width_, false);
}

void Screens::ExpandNetworkDropdown() {
  ShowInstructions("title_MiniOS_dropdown");
  ShowStepper({"1-done", "2", "3"});
  ShowLanguageMenu(false);
  ShowCollapsedNetworkDropDown(true);

  ShowNetworkDropdown();
  int items_on_page =
      std::min(kNetworksPerPage, static_cast<int>(network_list_.size()));
  ShowButton("btn_back", -frecon_canvas_size_ / 2 + 450 + (items_on_page * 40),
             (index_ == network_list_.size()), default_button_width_, false);
}

void Screens::ShowMiniOsGetPasswordScreen() {
  MessageBaseScreen();
  ShowInstructionsWithTitle("MiniOS_password");
  ShowStepper({"done", "2-done", "3"});
  ShowLanguageMenu(index_ == 0);
  constexpr int kBtnY = kTitleY + 58 + kBtnYStep * 2;
  ShowButton("Enter your password", kBtnY, false, default_button_width_ * 4,
             true);
  ShowButton("btn_back", kBtnY + kBtnYStep, (index_ == 2),
             default_button_width_, false);
}

void Screens::GetPassword() {
  std::string keyboard_layout;
  if (!MapRegionToKeyboard(&keyboard_layout)) {
    LOG(WARNING)
        << "Could not find xkb layout for given region. Defaulting to US.";
    keyboard_layout = "us";
  }
  key_reader::KeyReader password_key_reader =
      key_reader::KeyReader(/*include_usb=*/true, keyboard_layout);
  password_key_reader.InputSetUp();

  constexpr int kBtnY = kTitleY + 58 + kBtnYStep * 2;
  ShowButton("", kBtnY, false, default_button_width_ * 4, true);

  bool enter = false;
  bool show_password = false;
  std::string input;
  std::string plain_text_password;
  do {
    if (!password_key_reader.GetUserInput(&enter, &show_password, &input))
      continue;
    plain_text_password = input;
    if (!show_password) {
      input = std::string(input.size(), '*');
    }
    ShowButton(input, kBtnY, false, default_button_width_ * 4, true);
  } while (!enter);
  // TODO(vyshu) : Logging password for development purposes only. Remove.
  LOG(INFO) << "User password is: " << plain_text_password;

  // Connect to network.
  network_manager_->Connect(chosen_network_, plain_text_password);
}

void Screens::ShowMiniOsDownloadingScreen() {
  MessageBaseScreen();
  ShowInstructionsWithTitle("MiniOS_downloading");
  ShowStepper({"done", "done", "3-done"});
  ShowLanguageMenu(false);
  constexpr int kProgressHeight = 4;
  ShowBox(0, 0, 1000, kProgressHeight, kMenuGrey);
}

void Screens::ShowMiniOsCompleteScreen() {
  MessageBaseScreen();
  ShowInstructions("title_MiniOS_complete");
  ShowStepper({"done", "done", "done"});
  ShowLanguageMenu(false);
  // TODO(vyshu): Automatically reboot after timeout or on button selection.
  ShowButton("Reboot", -100, false, default_button_width_, true);
}

void Screens::ShowMiniOsErrorScreen() {
  MessageBaseScreen();
  ShowInstructionsWithTitle("MiniOS_general_error");
  ShowStepper({"done", "done", "stepper_error"});
  ShowLanguageMenu(index_ == 0);
  ShowButton("btn_try_again", -100, index_ == 1, default_button_width_, false);
}

void Screens::ShowMiniOsConnectionErrorScreen() {
  MessageBaseScreen();
  ShowInstructionsWithTitle("MiniOS_error");
  ShowStepper({"done", "done", "stepper_error"});
  ShowLanguageMenu(index_ == 0);
  ShowButton("btn_try_again", -100, index_ == 1, default_button_width_, false);
}

void Screens::UpdateButtons(int menu_count, int key, bool* enter) {
  int starting_index = index_;
  // Make sure index is in range, if not reset to 0.
  if (starting_index < 0 || starting_index >= menu_count)
    starting_index = 0;

  // Modify selected index and enter state based on user key input.
  if (key == kKeyUp || key == kKeyVolUp) {
    if (starting_index > 0) {
      starting_index--;
    }
  } else if (key == kKeyDown || key == kKeyVolDown) {
    if (starting_index < (menu_count - 1)) {
      starting_index++;
    }
  } else if (key == kKeyEnter || key == kKeyPower) {
    *enter = true;
  } else {
    LOG(ERROR) << "Unknown key value: " << key;
  }
  index_ = starting_index;
}

void Screens::ReadLangConstants() {
  lang_constants_.clear();
  supported_locales_.clear();
  // Read language widths from lang_constants.sh into memory.
  auto lang_constants_path = screens_path_.Append("lang_constants.sh");
  std::string const_values;
  if (!ReadFileToString(lang_constants_path, &const_values)) {
    LOG(ERROR) << "Could not read lang constants file " << lang_constants_path;
    return;
  }

  if (!base::SplitStringIntoKeyValuePairs(const_values, '=', '\n',
                                          &lang_constants_)) {
    LOG(ERROR) << "Unable to parse language width information.";
    return;
  }
  for (const auto& pair : lang_constants_) {
    if (pair.first == "SUPPORTED_LOCALES") {
      // Parse list of supported locales and store separately.
      std::string locale_list;
      if (!base::RemoveChars(pair.second, "\"", &locale_list))
        LOG(WARNING) << "Unable to remove surrounding quotes from locale list.";
      supported_locales_ = base::SplitString(
          locale_list, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    }
  }

  // Add size of language dropdown menu using the number of locales.
  menu_count_[ScreenType::kLanguageDropDownScreen] = supported_locales_.size();

  if (supported_locales_.empty()) {
    LOG(WARNING) << "Unable to get supported locales. Will not be able to "
                    "change locale.";
  }
}

bool Screens::GetLangConstants(const std::string& locale, int* lang_width) {
  if (lang_constants_.empty()) {
    LOG(ERROR) << "No language widths available.";
    return false;
  }

  // Lang_consts uses '_' while supported locale list uses '-'.
  std::string token;
  base::ReplaceChars(locale, "-", "_", &token);
  token = "LANGUAGE_" + token + "_WIDTH";

  // Find the width for the token.
  for (const auto& width_token : lang_constants_) {
    if (width_token.first == token) {
      if (!base::StringToInt(width_token.second, lang_width)) {
        LOG(ERROR) << "Could not convert " << width_token.second
                   << " to a number.";
        return false;
      }
      return true;
    }
  }
  return false;
}

void Screens::OnLocaleChange() {
  // Change locale and update constants.
  locale_ = supported_locales_[index_];
  CheckRightToLeft();
  ReadDimensionConstants();
  ClearScreen();
  ShowFooter();
  // Reset index state to go back to the MiniOs flow.
  index_ = 1;
}

void Screens::ShowCollapsedNetworkDropDown(bool is_selected) {
  const int kOffsetY = -frecon_canvas_size_ / 2 + 350;
  const int kBgX = -frecon_canvas_size_ / 2 + 145;
  const int kGlobeX = -frecon_canvas_size_ / 2 + 20;
  const int kArrowX = -frecon_canvas_size_ / 2 + 268;
  const int kTextX = -frecon_canvas_size_ / 2 + 100;

  // Currently using language and globe icons as placeholders.
  base::FilePath menu_background =
      is_selected ? screens_path_.Append("language_menu_bg_focused.png")
                  : screens_path_.Append("language_menu_bg.png");

  ShowImage(menu_background, kBgX, kOffsetY);
  ShowImage(screens_path_.Append("ic_language-globe.png"), kGlobeX, kOffsetY);
  ShowImage(screens_path_.Append("ic_dropdown.png"), kArrowX, kOffsetY);
  ShowMessage("btn_MiniOS_display_options", kTextX, kOffsetY);
}

void Screens::ShowNetworkDropdown() {
  int offset_y = -frecon_canvas_size_ / 2 + 350 + 40;
  const int kBackgroundX = -frecon_canvas_size_ / 2 + 360;
  const int kOffsetX = -frecon_canvas_size_ / 2 + 60;
  constexpr int kItemHeight = 40;

  if (network_list_.empty()) {
    // Okay to return here as there will be a callback to refresh the dropdown
    // once the networks are found.
    ShowBox(kBackgroundX, offset_y, 718, 38, kMenuDropdownBackgroundBlack);
    ShowText("Please wait while we find available networks.", kOffsetX,
             offset_y, "grey");
    return;
  }

  // Pick begin index such that the selected index is centered on the screen.
  // If there are not enough items for a full page then start at 0.
  int begin_index = 0;
  int page_difference = network_list_.size() - kNetworksPerPage;
  if (page_difference >= 0) {
    begin_index = std::clamp(index_ - kNetworksPerPage / 2, 0, page_difference);
  }

  for (int i = begin_index;
       i < (begin_index + kNetworksPerPage) && i < network_list_.size(); i++) {
    if (index_ == i) {
      ShowBox(kBackgroundX, offset_y, 720, 40, kMenuBlue);
      ShowText(network_list_[i], kOffsetX, offset_y, "black");
    } else {
      ShowBox(kBackgroundX, offset_y, 720, 40, kMenuDropdownFrameNavy);
      ShowBox(kBackgroundX, offset_y, 718, 38, kMenuDropdownBackgroundBlack);
      ShowText(network_list_[i], kOffsetX, offset_y, "grey");
    }
    offset_y += kItemHeight;
  }
}

void Screens::CheckRightToLeft() {
  // TODO(vyshu): Create an unblocked_terms.txt to allow "he" for Hebrew.
  right_to_left_ = (locale_ == "ar" || locale_ == "fa" || locale_ == "he");
}

void Screens::CheckDetachable() {
  is_detachable_ =
      base::PathExists(root_.Append("etc/cros-initramfs/is_detachable"));
}

void Screens::GetVpdRegion() {
  if (ReadFileToString(root_.Append("sys/firmware/vpd/ro/region"),
                       &vpd_region_)) {
    return;
  }
  LOG(WARNING) << "Could not read vpd region from file. Trying commandline.";
  int exit_code = 0;
  std::string error;
  if (!process_manager_->RunCommandWithOutput(
          {"/bin/vpd", "-g", "region"}, &exit_code, &vpd_region_, &error) ||
      exit_code) {
    vpd_region_ = "us";
    PLOG(WARNING) << "Error getting vpd -g region. Exit code " << exit_code
                  << " with error " << error << ". Defaulting to 'us'. ";
    return;
  }
  return;
}

void Screens::ReadHardwareId() {
  int exit_code = 0;
  std::string output, error;
  if (!process_manager_->RunCommandWithOutput({"/bin/crossystem", "hwid"},
                                              &exit_code, &output, &error) ||
      exit_code) {
    hwid_ = "CHROMEBOOK";
    PLOG(WARNING)
        << "Could not get hwid from crossystem. Exited with exit code "
        << exit_code << " and error " << error
        << ". Defaulting to 'CHROMEBOOK'.";
    return;
  }

  // Truncate HWID.
  std::vector<std::string> hwid_parts = base::SplitString(
      output, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  hwid_ = hwid_parts[0];
  return;
}

bool Screens::MapRegionToKeyboard(std::string* xkb_keyboard_layout) {
  std::string cros_region_json;
  if (!ReadFileToString(root_.Append("usr/share/misc/cros-regions.json"),
                        &cros_region_json)) {
    PLOG(ERROR) << "Could not read JSON mapping from cros-regions.json.";
    return false;
  }

  base::JSONReader::ValueWithError json_output =
      base::JSONReader::ReadAndReturnValueWithError(cros_region_json);
  if (!json_output.value || !json_output.value->is_dict()) {
    LOG(ERROR) << "Could not read json. " << json_output.error_message;
    return false;
  }

  // Look up mapping between vpd region and xkb keyboard layout.
  const base::Value* kRegionInfo = json_output.value->FindDictKey(vpd_region_);
  if (!kRegionInfo) {
    LOG(ERROR) << "Region " << vpd_region_ << " not found.";
    return false;
  }

  const base::Value* kKeyboard = kRegionInfo->FindListKey("keyboards");
  if (!kKeyboard || kKeyboard->GetList().empty()) {
    LOG(ERROR) << "Could not retrieve keyboards for given region "
               << vpd_region_
               << ". Available region information: " << *kRegionInfo;
    return false;
  }

  // Always use the first keyboard in the list.
  std::vector<std::string> keyboard_parts =
      base::SplitString(kKeyboard->GetList()[0].GetString(), ":",
                        base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  if (keyboard_parts.size() < 2) {
    LOG(ERROR) << "Could not parse keyboard information for region  "
               << vpd_region_;
    return false;
  }
  *xkb_keyboard_layout = keyboard_parts[1];
  return true;
}

void Screens::OnKeyPress(int fd_index, int key_changed, bool key_released) {
  // Make sure you have seen a key press for this key before ending on key
  // event release.

  if (fd_index < 0 || key_changed < 0 || fd_index >= key_states_.size() ||
      key_changed >= key_states_[0].size()) {
    LOG(ERROR) << "Fd index or key code out of range.  Index: " << fd_index
               << ". Key code: " << key_changed;
    return;
  }

  if (key_released && key_states_[fd_index][key_changed]) {
    key_states_[fd_index][key_changed] = false;
    bool enter = false;
    UpdateButtons(menu_count_[current_screen_], key_changed, &enter);
    SwitchScreen(enter);
    return;
  } else if (!key_released) {
    key_states_[fd_index][key_changed] = true;
  }
}

void Screens::SwitchScreen(bool enter) {
  // Changing locale. Remember the current screen to return back to it.
  if (enter && index_ == 0 &&
      current_screen_ != ScreenType::kLanguageDropDownScreen &&
      current_screen_ != ScreenType::kExpandedNetworkDropDownScreen &&
      current_screen_ != ScreenType::kStartDownload) {
    previous_screen_ = current_screen_;
    current_screen_ = ScreenType::kLanguageDropDownScreen;
    LanguageMenuOnSelect();
    return;
  }

  // Not switching to a different screen. Just update `current_screen_` with the
  // new index.
  if (!enter) {
    ShowNewScreen();
    return;
  }

  switch (current_screen_) {
    case ScreenType::kWelcomeScreen:
      if (index_ == 1) {
        current_screen_ = ScreenType::kNetworkDropDownScreen;
        // Update available networks every time the dropdown screen is picked.
        // TODO(vyshu): Change this to only update networks when necessary.
        UpdateNetworkList();
      }
      index_ = 1;
      break;
    case ScreenType::kNetworkDropDownScreen:
      if (index_ == 1) {
        index_ = 0;
        current_screen_ = ScreenType::kExpandedNetworkDropDownScreen;
        MessageBaseScreen();
      } else {
        index_ = 1;
        current_screen_ = ScreenType::kWelcomeScreen;
      }
      break;
    case ScreenType::kExpandedNetworkDropDownScreen:
      if (index_ == menu_count_[current_screen_] - 1) {
        index_ = 1;
        current_screen_ = ScreenType::kWelcomeScreen;
      } else if (network_list_.size() > index_ && index_ >= 0) {
        chosen_network_ = network_list_[index_];
        index_ = 1;
        current_screen_ = ScreenType::kPasswordScreen;
      } else {
        LOG(WARNING) << "Selected network index: " << index_
                     << " not valid. Retry";
        index_ = 0;
      }
      break;
    case ScreenType::kPasswordScreen:
      if (index_ == 1) {
        GetPassword();
        current_screen_ = ScreenType::kStartDownload;
      } else {
        index_ = 1;
        current_screen_ = ScreenType::kNetworkDropDownScreen;
        UpdateNetworkList();
      }
      break;
    case ScreenType::kLanguageDropDownScreen:
      if (enter) {
        current_screen_ = previous_screen_;
        OnLocaleChange();
        SwitchScreen(false);
        return;
      }
      break;
    case ScreenType::kStartDownload:
      return;
    case ScreenType::kDownloadError:
      if (index_ == 1) {
        // Back to beginning.
        current_screen_ = ScreenType::kWelcomeScreen;
      }
      break;
    case ScreenType::kNetworkError:
      if (index_ == 1) {
        // Back to dropdown screen,
        current_screen_ = ScreenType::kNetworkDropDownScreen;
      }
      break;
  }
  ShowNewScreen();
  return;
}

void Screens::ShowNewScreen() {
  switch (current_screen_) {
    case ScreenType::kWelcomeScreen:
      ShowMiniOsWelcomeScreen();
      break;
    case ScreenType::kNetworkDropDownScreen:
      ShowMiniOsNetworkDropdownScreen();
      break;
    case ScreenType::kExpandedNetworkDropDownScreen:
      ExpandNetworkDropdown();
      break;
    case ScreenType::kPasswordScreen:
      ShowMiniOsGetPasswordScreen();
      break;
    case ScreenType::kLanguageDropDownScreen:
      ShowLanguageDropdown();
      break;
    case ScreenType::kStartDownload:
      ShowMiniOsDownloadingScreen();
      break;
    case ScreenType::kDownloadError:
      ShowMiniOsErrorScreen();
      break;
    case ScreenType::kNetworkError:
      ShowMiniOsConnectionErrorScreen();
      break;
  }
}

void Screens::OnProgressChanged(const update_engine::StatusResult& status) {
  // Only make UI changes when needed to prevent unnecessary screen changes.
  if (!display_update_engine_state_)
    return;

  // Only reshow base screen if moving to a new update stage. This prevents
  // flickering as the screen repaints.
  update_engine::Operation operation = status.current_operation();
  switch (operation) {
    case update_engine::Operation::DOWNLOADING:
      if (previous_update_state_ != operation)
        ShowMiniOsDownloadingScreen();
      ShowProgressPercentage(status.progress());
      break;
    case update_engine::Operation::FINALIZING:
      if (previous_update_state_ != operation)
        LOG(INFO) << "Finalizing installation please wait.";
      // TODO(vyshu): Add a new screen and progress bar for this stage.
      break;
    case update_engine::Operation::UPDATED_NEED_REBOOT:
      ShowMiniOsCompleteScreen();
      // Don't make any more updates to the UI.
      display_update_engine_state_ = false;
      break;
    case update_engine::Operation::REPORTING_ERROR_EVENT:
    case update_engine::Operation::DISABLED:
    case update_engine::Operation::ERROR:
      LOG(ERROR) << "Could not finish the installation, failed with status: "
                 << status.current_operation();
      ChangeToDownloadErrorScreen();
      break;
    default:
      // Only `IDLE` and `CHECKING_FOR_UPDATE` can go back to `IDLE` without
      // any error.
      if (previous_update_state_ != update_engine::Operation::IDLE &&
          previous_update_state_ !=
              update_engine::Operation::CHECKING_FOR_UPDATE &&
          operation == update_engine::Operation::IDLE) {
        LOG(WARNING) << "Update engine went from " << operation
                     << "back to IDLE.";
        ChangeToDownloadErrorScreen();
      }
      break;
  }
  previous_update_state_ = operation;
}

void Screens::OnConnect(const std::string& ssid, brillo::Error* error) {
  if (error) {
    LOG(ERROR) << "Could not connect to " << ssid
               << ". ErrorCode=" << error->GetCode()
               << " ErrorMessage=" << error->GetMessage();
    ChangeToNetworkErrorScreen();
    return;
  }
  LOG(INFO) << "Successfully connected to " << ssid;
  // TODO(b/181248366): MiniOs: Stop update engine from scheduling periodic
  // update checks in recovery mode and then call update check manually.
  display_update_engine_state_ = true;
}

void Screens::OnGetNetworks(const std::vector<std::string>& networks,
                            brillo::Error* error) {
  if (error) {
    LOG(ERROR) << "Could not get networks. ErrorCode=" << error->GetCode()
               << " ErrorMessage=" << error->GetMessage();
    network_list_.clear();
    ChangeToNetworkErrorScreen();
    // Add one extra slot for the back button.
    menu_count_[ScreenType::kExpandedNetworkDropDownScreen] = 1;
    return;
  }
  network_list_ = networks;
  LOG(INFO) << "Trying to update network list.";

  // Change the menu count for the Expanded dropdown menu based on number of
  // networks. Add one extra slot for the back button.
  menu_count_[ScreenType::kExpandedNetworkDropDownScreen] =
      network_list_.size() + 1;

  if (network_list_.empty()) {
    LOG(ERROR) << "No available networks.";
    // TODO(vyshu) : Create a more specific error for this as it is not a
    // network error.
    ChangeToNetworkErrorScreen();
    return;
  }
  // If already waiting on the dropdown screen, refresh.
  if (current_screen_ == ScreenType::kExpandedNetworkDropDownScreen) {
    index_ = 0;
    ShowNewScreen();
  }
}

void Screens::UpdateNetworkList() {
  network_manager_->GetNetworks();
  chosen_network_.clear();
}
void Screens::ChangeToDownloadErrorScreen() {
  current_screen_ = ScreenType::kDownloadError;
  display_update_engine_state_ = false;
  index_ = 1;
  ShowNewScreen();
}
void Screens::ChangeToNetworkErrorScreen() {
  current_screen_ = ScreenType::kNetworkError;
  index_ = 1;
  ShowNewScreen();
  chosen_network_.clear();
}

}  // namespace screens
