// Copyright 2021 The ChromiumOS Authors
// 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 <memory>
#include <utility>
#include <vector>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/functional/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/key_reader.h"
#include "minios/metrics_reporter.h"
#include "minios/recovery_installer.h"
#include "minios/screen_types.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 {

namespace {

const base::FilePath kCurrentDisplayPath{"/run/frecon/current"};
const base::FilePath kUiDisplayPath{"/run/frecon/vt0"};

}  // namespace

ScreenController::ScreenController(
    std::shared_ptr<DrawInterface> draw_utils,
    std::shared_ptr<UpdateEngineProxy> update_engine_proxy,
    std::shared_ptr<NetworkManagerInterface> network_manager,
    std::shared_ptr<LogStoreManagerInterface> log_store_manager,
    std::shared_ptr<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_)}),
      log_store_manager_(log_store_manager) {}

bool ScreenController::Init() {
  if (!draw_utils_ || !draw_utils_->Init()) {
    LOG(ERROR) << AlertLogTag(kCategoryInit)
               << "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();

  frecon_screen_watcher_ = std::make_unique<base::FilePathWatcher>();
  frecon_screen_watcher_->Watch(
      kCurrentDisplayPath, base::FilePathWatcher::Type::kNonRecursive,
      base::BindRepeating(&::minios::ScreenController::OnDisplayChange,
                          base::Unretained(this)));

  if (log_store_manager_ && !log_store_manager_->Init()) {
    LOG(WARNING) << "Failed to initialize log store manager.";
    log_store_manager_ = nullptr;
  }

  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>(), log_store_manager_,
          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_,
                                                  log_store_manager_, this);
    case ScreenType::kLogScreen:
      return std::make_unique<ScreenLog>(draw_utils_, this);
    default:
      LOG(FATAL) << "Invalid screen.";
  }
}

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 previous screen, reset index.
      if (previous_screen_) {
        current_screen_ = std::move(previous_screen_);
        current_screen_->Reset();
      } else {
        // No screen saved. Go back to beginning.
        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::GoToScreen(ScreenType type, bool save_previous) {
  const auto current_type = current_screen_->GetType();
  if (current_type == ScreenType::kStartDownload) {
    // Return without changing screen if we have started recovery.
    LOG(ERROR) << "Screen change requested during download.";
    return;
  }
  if (save_previous) {
    previous_screen_ = std::move(current_screen_);
  }
  current_screen_ = CreateScreen(type);
  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 key) {
  CHECK(current_screen_) << "Could not send key event to screen.";

  if (key < 0 || key >= kKeyMax) {
    LOG(ERROR) << "Key code out of range. Key=" << key;
    return;
  }

  current_screen_->OnKeyPress(key);
}

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));
  } else {
    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;
  }
}

void ScreenController::OnDisplayChange(const base::FilePath& path, bool error) {
  // Disable key reader delegate when switching away from the UI display, enable
  // in all other cases.
  if (error) {
    LOG(ERROR) << "Enabling keyreader, error watching path=" << path;
    key_reader_.SetDelegate(this);
    return;
  }

  base::FilePath resolved_path;
  if (base::ReadSymbolicLink(path, &resolved_path) &&
      resolved_path != kUiDisplayPath) {
    LOG(INFO) << "Disabling key reader due to display change.";
    key_reader_.SetDelegate(nullptr);
    return;
  }
  LOG(INFO) << "Enabling key reader.";
  key_reader_.SetDelegate(this);
}

}  // namespace minios
