// 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/screen_controller.h"

#include <utility>

#include <base/callback.h>
#include <base/logging.h>
#include <base/strings/strcat.h>
#include <base/time/time.h>
#include <brillo/message_loops/message_loop.h>

#include "minios/error.h"
#include "minios/recovery_installer.h"
#include "minios/screens/screen_debug_options.h"
#include "minios/screens/screen_download.h"
#include "minios/screens/screen_error.h"
#include "minios/screens/screen_language_dropdown.h"
#include "minios/screens/screen_log.h"
#include "minios/screens/screen_network.h"
#include "minios/screens/screen_permission.h"
#include "minios/screens/screen_welcome.h"
#include "minios/utils.h"

namespace minios {

ScreenController::ScreenController(
    std::shared_ptr<DrawInterface> draw_utils,
    std::shared_ptr<UpdateEngineProxy> update_engine_proxy,
    std::shared_ptr<NetworkManagerInterface> network_manager,
    ProcessManagerInterface* process_manager)
    : draw_utils_(draw_utils),
      update_engine_proxy_(update_engine_proxy),
      network_manager_(network_manager),
      process_manager_(process_manager),
      key_reader_(
          KeyReader{/*include_usb=*/true, GetKeyboardLayout(process_manager_)}),
      key_states_(kFdsMax, std::vector<bool>(kKeyMax, false)) {}

bool ScreenController::Init() {
  if (!draw_utils_ || !draw_utils_->Init()) {
    LOG(ERROR) << "Screen drawing utility not available. Cannot continue.";
    return false;
  }
  update_engine_proxy_->Init();

  std::vector<int> wait_keys = {KEY_UP, KEY_DOWN, KEY_ENTER, KEY_ESC};
  if (draw_utils_->IsDetachable())
    wait_keys = {KEY_VOLUMEDOWN, KEY_VOLUMEUP, KEY_POWER, KEY_ESC};
  if (!key_reader_.Init(wait_keys)) {
    LOG(ERROR) << "Could not initialize key reader. Unable to continue.";
    return false;
  }

  key_reader_.SetDelegate(this);

  current_screen_ = CreateScreen(ScreenType::kWelcomeScreen);
  current_screen_->Show();
  return true;
}

std::unique_ptr<ScreenInterface> ScreenController::CreateScreen(
    ScreenType screen_type) {
  switch (screen_type) {
    case ScreenType::kWelcomeScreen:
      return std::make_unique<ScreenWelcome>(draw_utils_, this);
    case ScreenType::kNetworkDropDownScreen: {
      auto screen = std::make_unique<ScreenNetwork>(
          draw_utils_, network_manager_, &key_reader_, this);
      if (!seeded_ssid_.empty()) {
        screen->SeedCredentials(seeded_ssid_, seeded_passphrase_);
      }
      return screen;
    }
    case ScreenType::kLanguageDropDownScreen:
      return std::make_unique<ScreenLanguageDropdown>(draw_utils_, this);
    case ScreenType::kUserPermissionScreen:
      return std::make_unique<ScreenPermission>(draw_utils_, this);
    case ScreenType::kStartDownload:
      return std::make_unique<ScreenDownload>(
          std::make_unique<RecoveryInstaller>(process_manager_),
          update_engine_proxy_, draw_utils_,
          std::make_unique<MetricsReporter>(process_manager_), this);
    case ScreenType::kDownloadError:
    case ScreenType::kNetworkError:
    case ScreenType::kPasswordError:
    case ScreenType::kConnectionError:
    case ScreenType::kGeneralError:
      return std::make_unique<ScreenError>(screen_type, draw_utils_, this);
    case ScreenType::kDebugOptionsScreen:
      return std::make_unique<ScreenDebugOptions>(draw_utils_, this);
    case ScreenType::kLogScreen:
      return std::make_unique<ScreenLog>(draw_utils_, this);
    default:
      LOG(FATAL) << "Invalid screen.";
      return nullptr;
  }
}

void ScreenController::OnForward(ScreenInterface* screen) {
  switch (screen->GetType()) {
    case ScreenType::kWelcomeScreen:
      current_screen_ = CreateScreen(ScreenType::kNetworkDropDownScreen);
      break;
    case ScreenType::kNetworkDropDownScreen:
      current_screen_ = CreateScreen(ScreenType::kUserPermissionScreen);
      break;
    case ScreenType::kUserPermissionScreen:
      current_screen_ = CreateScreen(ScreenType::kStartDownload);
      break;
    case ScreenType::kDownloadError:
    case ScreenType::kNetworkError:
    case ScreenType::kPasswordError:
    case ScreenType::kConnectionError:
    case ScreenType::kGeneralError:
      // Show debug options and log screen. Save error screen to return to from
      // `kDebugOptionsScreen`.
      previous_screen_ = std::move(current_screen_);
      current_screen_ = CreateScreen(ScreenType::kDebugOptionsScreen);
      break;
    case ScreenType::kDebugOptionsScreen:
      current_screen_ = CreateScreen(ScreenType::kLogScreen);
      break;
    default:
      LOG(FATAL) << "Invalid screen.";
  }
  current_screen_->Show();
}

void ScreenController::OnBackward(ScreenInterface* screen) {
  switch (screen->GetType()) {
    case ScreenType::kWelcomeScreen:
    case ScreenType::kNetworkDropDownScreen:
    case ScreenType::kUserPermissionScreen:
      previous_screen_ = nullptr;
      current_screen_ = CreateScreen(ScreenType::kWelcomeScreen);
      break;
    case ScreenType::kPasswordError:
    case ScreenType::kNetworkError:
    case ScreenType::kConnectionError:
      // Return to network dropdown screen.
      previous_screen_ = nullptr;
      current_screen_ = CreateScreen(ScreenType::kNetworkDropDownScreen);
      break;
    case ScreenType::kDownloadError:
    case ScreenType::kGeneralError:
      // Return to beginning of the flow.
      previous_screen_ = nullptr;
      current_screen_ = CreateScreen(ScreenType::kWelcomeScreen);
      break;
    case ScreenType::kDebugOptionsScreen:
      // Back to original error screen, reset index.
      if (previous_screen_ &&
          dynamic_cast<ScreenError*>(previous_screen_.get())) {
        current_screen_ = std::move(previous_screen_);
        current_screen_->Reset();
      } else {
        // No error screen saved. Go back to beginning.
        previous_screen_ = nullptr;
        current_screen_ = CreateScreen(ScreenType::kWelcomeScreen);
      }
      break;
    case ScreenType::kLogScreen:
      // Back to debug options screen.
      current_screen_ = CreateScreen(ScreenType::kDebugOptionsScreen);
      break;
    case ScreenType::kLanguageDropDownScreen:
      if (previous_screen_) {
        current_screen_ = std::move(previous_screen_);
      } else {
        current_screen_ = CreateScreen(ScreenType::kWelcomeScreen);
      }
      break;
    default:
      LOG(FATAL) << "Invalid screen.";
  }
  current_screen_->Show();
}

void ScreenController::OnError(ScreenType error_screen) {
  switch (error_screen) {
    case ScreenType::kDownloadError:
    case ScreenType::kNetworkError:
    case ScreenType::kPasswordError:
    case ScreenType::kConnectionError:
    case ScreenType::kGeneralError:
      previous_screen_ = std::move(current_screen_);
      current_screen_ = CreateScreen(error_screen);
      break;
    default:
      LOG(WARNING)
          << "Not a valid error screen. Defaulting to general error case.";
      previous_screen_ = std::move(current_screen_);
      current_screen_ = CreateScreen(ScreenType::kGeneralError);
      break;
  }
  current_screen_->Show();
}

ScreenType ScreenController::GetCurrentScreen() {
  return current_screen_->GetType();
}

void ScreenController::SwitchLocale(ScreenInterface* screen) {
  previous_screen_ = std::move(current_screen_);
  current_screen_ = CreateScreen(ScreenType::kLanguageDropDownScreen);
  current_screen_->Show();
}

void ScreenController::UpdateLocale(ScreenInterface* screen,
                                    int selected_locale_index) {
  // Change locale and update constants.
  CHECK(draw_utils_) << "Screen drawing utility not available.";
  if (screen->GetType() != ScreenType::kLanguageDropDownScreen) {
    LOG(WARNING) << "Only the language dropdown screen can change the locale.";
    return;
  }
  draw_utils_->LocaleChange(selected_locale_index);
  current_screen_ = std::move(previous_screen_);
  current_screen_->Reset();
  current_screen_->Show();
}

void ScreenController::OnKeyPress(int fd_index,
                                  int key_changed,
                                  bool key_released) {
  CHECK(current_screen_) << "Could not send key event to screen.";

  // 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;
    // Send key event to the currently displayed screen. It will decide what to
    // do with it.
    current_screen_->OnKeyPress(key_changed);
    return;
  } else if (!key_released) {
    key_states_[fd_index][key_changed] = true;
  }
}

void ScreenController::GetState(State* state_out) {
  CHECK(current_screen_) << "Could not get State for current screen.";
  state_out->CopyFrom(current_screen_->GetState());
}

bool ScreenController::MoveBackward(brillo::ErrorPtr* error) {
  CHECK(current_screen_) << "Could not move to previous screen.";
  LOG(INFO) << "MoveBackward from screen: " << current_screen_->GetName();
  return current_screen_->MoveBackward(error);
}

bool ScreenController::MoveForward(brillo::ErrorPtr* error) {
  CHECK(current_screen_) << "Could not move to next screen.";
  LOG(INFO) << "MoveForward from screen: " << current_screen_->GetName();
  return current_screen_->MoveForward(error);
}

void ScreenController::PressKey(int key_changed) {
  CHECK(current_screen_) << "Could not send key event to screen.";
  // TODO(hbarnor): Does not support GetPassword screen. Need to look into using
  // `KeyReader` for this.
  current_screen_->OnKeyPress(key_changed);
}

bool ScreenController::Reset(brillo::ErrorPtr* error) {
  if (ResetScreen(error)) {
    seeded_ssid_.clear();
    seeded_passphrase_.clear();
    dbus_recovery_state_.reset();
    return true;
  }
  return false;
}

bool ScreenController::ResetScreen(brillo::ErrorPtr* error) {
  // Don't allow reset in the middle of recovering.
  if (current_screen_->GetType() == ScreenType::kStartDownload) {
    Error::AddTo(error, FROM_HERE, error::kCannotReset,
                 "Cannot reset whiles recovery in progress.");

    return false;
  }
  previous_screen_ = nullptr;
  current_screen_ = CreateScreen(ScreenType::kWelcomeScreen);
  current_screen_->Show();
  return true;
}

void ScreenController::SeedNetworkCredentials(const std::string& ssid,
                                              const std::string& passphrase) {
  seeded_ssid_ = ssid;
  seeded_passphrase_ = passphrase;
  if (current_screen_->GetType() == ScreenType::kNetworkDropDownScreen) {
    ScreenNetwork* screen = dynamic_cast<ScreenNetwork*>(current_screen_.get());
    if (screen)
      screen->SeedCredentials(seeded_ssid_, seeded_passphrase_);
  }
}

void ScreenController::StartRecovery(const std::string& ssid,
                                     const std::string& passphrase) {
  if (dbus_recovery_state_.has_value()) {
    LOG(ERROR) << "Recovery already in progress.;";
    return;
  }
  dbus_recovery_state_ = State::IDLE;
  brillo::ErrorPtr error;
  LOG(INFO) << "Starting Dbus triggered recovery flow.;";
  // Always start from welcome screen.
  bool result = ResetScreen(&error);
  if (result) {
    SeedNetworkCredentials(ssid, passphrase);
    // Move forward from welcome screen.
    brillo::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::BindOnce(base::IgnoreResult(&ScreenController::MoveForward),
                       base::Unretained(this), nullptr));
  }

  if (!result) {
    LOG(ERROR) << "StartRecovery failed. Reason: " << error->GetMessage();

    if (dbus_recovery_state_.value() != State::ERROR)
      OnError(ScreenType::kGeneralError);
  }
}

void ScreenController::SetStateReporter(
    StateReporterInterface* state_reporter) {
  state_reporter_ = state_reporter;
}

void ScreenController::OnStateChanged(State state) {
  if (state_reporter_) {
    // StateChanged observers cannot/should not modify state.
    state_reporter_->StateChanged(state);
  }
  HandleStateChanged(state.state());
}

void ScreenController::HandleStateChanged(State::States state_state) {
  if (!dbus_recovery_state_.has_value() ||
      (dbus_recovery_state_.value() == state_state))
    return;

  LOG(INFO) << "Recovery flow transitioning state: "
            << State_States_Name(dbus_recovery_state_.value()) << " -> "
            << State_States_Name(state_state);
  dbus_recovery_state_ = state_state;
  switch (state_state) {
    case State::CONNECTED:
    case State::NETWORK_CREDENTIALS:
    case State::NETWORK_SELECTION: {
      brillo::MessageLoop::current()->PostTask(
          FROM_HERE,
          base::BindOnce(base::IgnoreResult(&ScreenController::MoveForward),
                         base::Unretained(this), nullptr));

      break;
    }
    case State::ERROR:
    case State::COMPLETED: {
      seeded_ssid_.clear();
      seeded_passphrase_.clear();
      dbus_recovery_state_.reset();
      break;
    }
    default:
      break;
  }
}

}  // namespace minios
