// Copyright 2017 The Chromium 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 "ash/login/login_screen_controller.h"

#include <utility>

#include "ash/focus_cycler.h"
#include "ash/login/ui/lock_screen.h"
#include "ash/login/ui/login_data_dispatcher.h"
#include "ash/public/cpp/ash_pref_names.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/login_shelf_view.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/status_area_widget_delegate.h"
#include "ash/system/toast/toast_data.h"
#include "ash/system/toast/toast_manager.h"
#include "ash/system/tray/system_tray_notifier.h"
#include "base/bind.h"
#include "base/debug/alias.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/session_manager/session_manager_types.h"

namespace ash {

namespace {

enum class SystemTrayVisibility {
  kNone,     // Tray not visible anywhere.
  kPrimary,  // Tray visible only on primary display.
  kAll,      // Tray visible on all displays.
};

void SetSystemTrayVisibility(SystemTrayVisibility visibility) {
  RootWindowController* primary_window_controller =
      Shell::GetPrimaryRootWindowController();
  for (RootWindowController* window_controller :
       Shell::GetAllRootWindowControllers()) {
    StatusAreaWidget* status_area = window_controller->GetStatusAreaWidget();
    if (!status_area)
      continue;
    if (window_controller == primary_window_controller) {
      status_area->SetSystemTrayVisibility(
          visibility == SystemTrayVisibility::kPrimary ||
          visibility == SystemTrayVisibility::kAll);
    } else {
      status_area->SetSystemTrayVisibility(visibility ==
                                           SystemTrayVisibility::kAll);
    }
  }
}

}  // namespace

LoginScreenController::LoginScreenController(
    SystemTrayNotifier* system_tray_notifier)
    : system_tray_notifier_(system_tray_notifier), weak_factory_(this) {
  system_tray_notifier_->AddSystemTrayFocusObserver(this);
}

LoginScreenController::~LoginScreenController() {
  system_tray_notifier_->RemoveSystemTrayFocusObserver(this);
}

// static
void LoginScreenController::RegisterProfilePrefs(PrefRegistrySimple* registry,
                                                 bool for_test) {
  if (for_test) {
    // There is no remote pref service, so pretend that ash owns the pref.
    registry->RegisterStringPref(prefs::kQuickUnlockPinSalt, "");
    return;
  }
}

void LoginScreenController::BindRequest(mojom::LoginScreenRequest request) {
  bindings_.AddBinding(this, std::move(request));
}

bool LoginScreenController::IsAuthenticating() const {
  return authentication_stage_ != AuthenticationStage::kIdle;
}

void LoginScreenController::AuthenticateUserWithPasswordOrPin(
    const AccountId& account_id,
    const std::string& password,
    bool authenticated_by_pin,
    OnAuthenticateCallback callback) {
  // It is an error to call this function while an authentication is in
  // progress.
  LOG_IF(FATAL, IsAuthenticating())
      << "Duplicate authentication attempt; current authentication stage is "
      << static_cast<int>(authentication_stage_);

  if (!login_screen_client_) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  // If auth is disabled by the debug overlay bypass the mojo call entirely, as
  // it will dismiss the lock screen if the password is correct.
  switch (force_fail_auth_for_debug_overlay_) {
    case ForceFailAuth::kOff:
      break;
    case ForceFailAuth::kImmediate:
      OnAuthenticateComplete(std::move(callback), false /*success*/);
      return;
    case ForceFailAuth::kDelayed:
      // Set a dummy authentication stage so that |IsAuthenticating| returns
      // true.
      authentication_stage_ = AuthenticationStage::kDoAuthenticate;
      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&LoginScreenController::OnAuthenticateComplete,
                         weak_factory_.GetWeakPtr(), base::Passed(&callback),
                         false),
          base::TimeDelta::FromSeconds(1));
      return;
  }

  authentication_stage_ = AuthenticationStage::kDoAuthenticate;

  int dummy_value;
  bool is_pin =
      authenticated_by_pin && base::StringToInt(password, &dummy_value);
  login_screen_client_->AuthenticateUserWithPasswordOrPin(
      account_id, password, is_pin,
      base::BindOnce(&LoginScreenController::OnAuthenticateComplete,
                     weak_factory_.GetWeakPtr(), base::Passed(&callback)));
}

void LoginScreenController::AuthenticateUserWithExternalBinary(
    const AccountId& account_id,
    OnAuthenticateCallback callback) {
  // It is an error to call this function while an authentication is in
  // progress.
  LOG_IF(FATAL, IsAuthenticating())
      << "Duplicate authentication attempt; current authentication stage is "
      << static_cast<int>(authentication_stage_);

  if (!login_screen_client_) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  authentication_stage_ = AuthenticationStage::kDoAuthenticate;
  login_screen_client_->AuthenticateUserWithExternalBinary(
      account_id,
      base::BindOnce(&LoginScreenController::OnAuthenticateComplete,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void LoginScreenController::EnrollUserWithExternalBinary(
    OnAuthenticateCallback callback) {
  if (!login_screen_client_) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  login_screen_client_->EnrollUserWithExternalBinary(base::BindOnce(
      [](OnAuthenticateCallback callback, bool success) {
        std::move(callback).Run(base::make_optional<bool>(success));
      },
      std::move(callback)));
}

void LoginScreenController::AuthenticateUserWithEasyUnlock(
    const AccountId& account_id) {
  // TODO(jdufault): integrate this into authenticate stage after mojom is
  // refactored to use a callback.
  if (!login_screen_client_)
    return;
  login_screen_client_->AuthenticateUserWithEasyUnlock(account_id);
}

void LoginScreenController::ValidateParentAccessCode(
    const AccountId& account_id,
    const std::string& code,
    OnParentAccessValidation callback) {
  if (!login_screen_client_) {
    std::move(callback).Run(base::nullopt);
    return;
  }

  login_screen_client_->ValidateParentAccessCode(
      account_id, code,
      base::BindOnce(&LoginScreenController::OnParentAccessValidationComplete,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void LoginScreenController::HardlockPod(const AccountId& account_id) {
  if (!login_screen_client_)
    return;
  login_screen_client_->HardlockPod(account_id);
}

void LoginScreenController::OnFocusPod(const AccountId& account_id) {
  if (!login_screen_client_)
    return;
  login_screen_client_->OnFocusPod(account_id);
}

void LoginScreenController::OnNoPodFocused() {
  if (!login_screen_client_)
    return;
  login_screen_client_->OnNoPodFocused();
}

void LoginScreenController::LoadWallpaper(const AccountId& account_id) {
  if (!login_screen_client_)
    return;
  login_screen_client_->LoadWallpaper(account_id);
}

void LoginScreenController::SignOutUser() {
  if (!login_screen_client_)
    return;
  login_screen_client_->SignOutUser();
}

void LoginScreenController::CancelAddUser() {
  if (!login_screen_client_)
    return;
  login_screen_client_->CancelAddUser();
}

void LoginScreenController::LoginAsGuest() {
  if (!login_screen_client_)
    return;
  login_screen_client_->LoginAsGuest();
}

void LoginScreenController::OnMaxIncorrectPasswordAttempted(
    const AccountId& account_id) {
  if (!login_screen_client_)
    return;
  login_screen_client_->OnMaxIncorrectPasswordAttempted(account_id);
}

void LoginScreenController::FocusLockScreenApps(bool reverse) {
  if (!login_screen_client_)
    return;
  login_screen_client_->FocusLockScreenApps(reverse);
}

void LoginScreenController::ShowGaiaSignin(
    bool can_close,
    const base::Optional<AccountId>& prefilled_account) {
  if (!login_screen_client_)
    return;
  login_screen_client_->ShowGaiaSignin(can_close, prefilled_account);
}

void LoginScreenController::OnRemoveUserWarningShown() {
  if (!login_screen_client_)
    return;
  login_screen_client_->OnRemoveUserWarningShown();
}

void LoginScreenController::RemoveUser(const AccountId& account_id) {
  if (!login_screen_client_)
    return;
  login_screen_client_->RemoveUser(account_id);
}

void LoginScreenController::LaunchPublicSession(
    const AccountId& account_id,
    const std::string& locale,
    const std::string& input_method) {
  if (!login_screen_client_)
    return;
  login_screen_client_->LaunchPublicSession(account_id, locale, input_method);
}

void LoginScreenController::RequestPublicSessionKeyboardLayouts(
    const AccountId& account_id,
    const std::string& locale) {
  if (!login_screen_client_)
    return;
  login_screen_client_->RequestPublicSessionKeyboardLayouts(account_id, locale);
}

void LoginScreenController::ShowFeedback() {
  if (!login_screen_client_)
    return;
  login_screen_client_->ShowFeedback();
}

void LoginScreenController::AddObserver(
    LoginScreenControllerObserver* observer) {
  observers_.AddObserver(observer);
}

void LoginScreenController::RemoveObserver(
    LoginScreenControllerObserver* observer) {
  observers_.RemoveObserver(observer);
}

void LoginScreenController::FlushForTesting() {
  login_screen_client_.FlushForTesting();
}

void LoginScreenController::SetClient(mojom::LoginScreenClientPtr client) {
  login_screen_client_ = std::move(client);
}

void LoginScreenController::ShowLockScreen(ShowLockScreenCallback on_shown) {
  OnShow();
  ash::LockScreen::Show(ash::LockScreen::ScreenType::kLock);
  std::move(on_shown).Run(true);
}

void LoginScreenController::ShowLoginScreen(ShowLoginScreenCallback on_shown) {
  // Login screen can only be used during login.
  if (Shell::Get()->session_controller()->GetSessionState() !=
      session_manager::SessionState::LOGIN_PRIMARY) {
    LOG(ERROR) << "Not showing login screen since session state is "
               << static_cast<int>(
                      Shell::Get()->session_controller()->GetSessionState());
    std::move(on_shown).Run(false);
    return;
  }

  OnShow();
  // TODO(jdufault): rename ash::LockScreen to ash::LoginScreen.
  ash::LockScreen::Show(ash::LockScreen::ScreenType::kLogin);
  std::move(on_shown).Run(true);
}

void LoginScreenController::ShowErrorMessage(int32_t login_attempts,
                                             const std::string& error_text,
                                             const std::string& help_link_text,
                                             int32_t help_topic_id) {
  NOTIMPLEMENTED();
}

void LoginScreenController::ShowWarningBanner(const base::string16& message) {
  if (DataDispatcher())
    DataDispatcher()->ShowWarningBanner(message);
}

void LoginScreenController::HideWarningBanner() {
  if (DataDispatcher())
    DataDispatcher()->HideWarningBanner();
}

void LoginScreenController::ClearErrors() {
  NOTIMPLEMENTED();
}

void LoginScreenController::ShowUserPodCustomIcon(
    const AccountId& account_id,
    mojom::EasyUnlockIconOptionsPtr icon) {
  DataDispatcher()->ShowEasyUnlockIcon(account_id, icon);
}

void LoginScreenController::HideUserPodCustomIcon(const AccountId& account_id) {
  auto icon_options = mojom::EasyUnlockIconOptions::New();
  icon_options->icon = mojom::EasyUnlockIconId::NONE;
  DataDispatcher()->ShowEasyUnlockIcon(account_id, icon_options);
}

void LoginScreenController::SetAuthType(
    const AccountId& account_id,
    proximity_auth::mojom::AuthType auth_type,
    const base::string16& initial_value) {
  if (auth_type == proximity_auth::mojom::AuthType::USER_CLICK) {
    DataDispatcher()->SetTapToUnlockEnabledForUser(account_id,
                                                   true /*enabled*/);
  } else if (auth_type == proximity_auth::mojom::AuthType::ONLINE_SIGN_IN) {
    DataDispatcher()->SetForceOnlineSignInForUser(account_id);
  } else {
    NOTIMPLEMENTED();
  }
}

void LoginScreenController::SetUserList(
    std::vector<mojom::LoginUserInfoPtr> users) {
  DCHECK(DataDispatcher());

  DataDispatcher()->NotifyUsers(users);
}

void LoginScreenController::SetPinEnabledForUser(const AccountId& account_id,
                                                 bool is_enabled) {
  // Chrome will update pin pod state every time user tries to authenticate.
  // LockScreen is destroyed in the case of authentication success.
  if (DataDispatcher())
    DataDispatcher()->SetPinEnabledForUser(account_id, is_enabled);
}

void LoginScreenController::SetFingerprintState(const AccountId& account_id,
                                                mojom::FingerprintState state) {
  if (DataDispatcher())
    DataDispatcher()->SetFingerprintState(account_id, state);
}

void LoginScreenController::NotifyFingerprintAuthResult(
    const AccountId& account_id,
    bool successful) {
  if (DataDispatcher())
    DataDispatcher()->NotifyFingerprintAuthResult(account_id, successful);
}

void LoginScreenController::SetAvatarForUser(const AccountId& account_id,
                                             mojom::UserAvatarPtr avatar) {
  for (auto& observer : observers_)
    observer.SetAvatarForUser(account_id, avatar);
}

void LoginScreenController::EnableAuthForUser(const AccountId& account_id) {
  if (DataDispatcher())
    DataDispatcher()->EnableAuthForUser(account_id);
}

void LoginScreenController::DisableAuthForUser(
    const AccountId& account_id,
    ash::mojom::AuthDisabledDataPtr auth_disabled_data) {
  if (DataDispatcher()) {
    DataDispatcher()->DisableAuthForUser(account_id,
                                         std::move(auth_disabled_data));
  }
}

void LoginScreenController::HandleFocusLeavingLockScreenApps(bool reverse) {
  for (auto& observer : observers_)
    observer.OnFocusLeavingLockScreenApps(reverse);
}

void LoginScreenController::SetSystemInfo(
    bool show_if_hidden,
    const std::string& os_version_label_text,
    const std::string& enterprise_info_text,
    const std::string& bluetooth_name) {
  if (DataDispatcher()) {
    DataDispatcher()->SetSystemInfo(show_if_hidden, os_version_label_text,
                                    enterprise_info_text, bluetooth_name);
  }
}

void LoginScreenController::IsReadyForPassword(
    IsReadyForPasswordCallback callback) {
  std::move(callback).Run(LockScreen::HasInstance() && !IsAuthenticating());
}

void LoginScreenController::SetPublicSessionDisplayName(
    const AccountId& account_id,
    const std::string& display_name) {
  if (DataDispatcher())
    DataDispatcher()->SetPublicSessionDisplayName(account_id, display_name);
}

void LoginScreenController::SetPublicSessionLocales(
    const AccountId& account_id,
    std::vector<mojom::LocaleItemPtr> locales,
    const std::string& default_locale,
    bool show_advanced_view) {
  if (DataDispatcher()) {
    DataDispatcher()->SetPublicSessionLocales(
        account_id, locales, default_locale, show_advanced_view);
  }
}

void LoginScreenController::SetPublicSessionKeyboardLayouts(
    const AccountId& account_id,
    const std::string& locale,
    std::vector<mojom::InputMethodItemPtr> keyboard_layouts) {
  if (DataDispatcher()) {
    DataDispatcher()->SetPublicSessionKeyboardLayouts(account_id, locale,
                                                      keyboard_layouts);
  }
}

void LoginScreenController::SetPublicSessionShowFullManagementDisclosure(
    bool is_full_management_disclosure_needed) {
  if (DataDispatcher()) {
    DataDispatcher()->SetPublicSessionShowFullManagementDisclosure(
        is_full_management_disclosure_needed);
  }
}

void LoginScreenController::ShowKioskAppError(const std::string& message) {
  ToastData toast_data(
      "KioskAppError", base::UTF8ToUTF16(message), -1 /*duration_ms*/,
      base::Optional<base::string16>(base::string16()) /*dismiss_text*/,
      true /*visible_on_lock_screen*/);
  Shell::Get()->toast_manager()->Show(toast_data);
}

void LoginScreenController::NotifyOobeDialogState(
    mojom::OobeDialogState state) {
  for (auto& observer : observers_)
    observer.OnOobeDialogStateChanged(state);
}

void LoginScreenController::SetAllowLoginAsGuest(bool allow_guest) {
  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
      ->shelf_widget()
      ->login_shelf_view()
      ->SetAllowLoginAsGuest(allow_guest);
}

void LoginScreenController::SetShowGuestButtonInOobe(bool show) {
  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
      ->shelf_widget()
      ->login_shelf_view()
      ->SetShowGuestButtonInOobe(show);
}

void LoginScreenController::SetShowParentAccessButton(bool show) {
  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
      ->shelf_widget()
      ->login_shelf_view()
      ->SetShowParentAccessButton(show);
}

void LoginScreenController::SetShowParentAccessDialog(bool show) {
  if (DataDispatcher())
    DataDispatcher()->SetShowParentAccessDialog(show);
}

void LoginScreenController::FocusLoginShelf(bool reverse) {
  Shelf* shelf = Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow());
  // Tell the focus direction to the status area or the shelf so they can focus
  // the correct child view.
  if (reverse || !ShelfWidget::IsUsingViewsShelf()) {
    if (!Shell::GetPrimaryRootWindowController()->IsSystemTrayVisible())
      return;
    shelf->GetStatusAreaWidget()
        ->status_area_widget_delegate()
        ->set_default_last_focusable_child(reverse);
    Shell::Get()->focus_cycler()->FocusWidget(shelf->GetStatusAreaWidget());
  } else {
    shelf->shelf_widget()->set_default_last_focusable_child(reverse);
    Shell::Get()->focus_cycler()->FocusWidget(shelf->shelf_widget());
  }
}

void LoginScreenController::SetKioskApps(
    const std::vector<KioskAppMenuEntry>& kiosk_apps,
    const base::RepeatingCallback<void(const KioskAppMenuEntry&)>& launch_app) {
  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
      ->shelf_widget()
      ->login_shelf_view()
      ->SetKioskApps(kiosk_apps, launch_app);
}

void LoginScreenController::SetAddUserButtonEnabled(bool enable) {
  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
      ->shelf_widget()
      ->login_shelf_view()
      ->SetAddUserButtonEnabled(enable);
}

void LoginScreenController::SetShutdownButtonEnabled(bool enable) {
  Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
      ->shelf_widget()
      ->login_shelf_view()
      ->SetShutdownButtonEnabled(enable);
}

void LoginScreenController::ShowResetScreen() {
  login_screen_client_->ShowResetScreen();
}

void LoginScreenController::ShowAccountAccessHelpApp() {
  login_screen_client_->ShowAccountAccessHelpApp();
}

void LoginScreenController::FocusOobeDialog() {
  if (!login_screen_client_)
    return;
  login_screen_client_->FocusOobeDialog();
}

void LoginScreenController::NotifyUserActivity() {
  if (!login_screen_client_)
    return;
  login_screen_client_->OnUserActivity();
}

void LoginScreenController::OnAuthenticateComplete(
    OnAuthenticateCallback callback,
    bool success) {
  authentication_stage_ = AuthenticationStage::kUserCallback;
  std::move(callback).Run(base::make_optional<bool>(success));
  authentication_stage_ = AuthenticationStage::kIdle;
}

void LoginScreenController::OnParentAccessValidationComplete(
    OnParentAccessValidation callback,
    bool success) {
  std::move(callback).Run(base::make_optional<bool>(success));
}

LoginDataDispatcher* LoginScreenController::DataDispatcher() const {
  if (!ash::LockScreen::HasInstance())
    return nullptr;
  return ash::LockScreen::Get()->data_dispatcher();
}

void LoginScreenController::OnShow() {
  SetSystemTrayVisibility(SystemTrayVisibility::kPrimary);
  if (authentication_stage_ != AuthenticationStage::kIdle) {
    AuthenticationStage authentication_stage = authentication_stage_;
    base::debug::Alias(&authentication_stage);
    LOG(FATAL) << "Unexpected authentication stage "
               << static_cast<int>(authentication_stage_);
  }
}

void LoginScreenController::OnFocusLeavingSystemTray(bool reverse) {
  if (!login_screen_client_)
    return;
  login_screen_client_->OnFocusLeavingSystemTray(reverse);
}

}  // namespace ash
