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

#include "ash/in_session_auth/authentication_dialog.h"

#include <memory>

#include "ash/constants/ash_features.h"
#include "ash/public/cpp/in_session_auth_dialog_controller.h"
#include "ash/public/cpp/in_session_auth_token_provider.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "chromeos/ash/components/cryptohome/common_types.h"
#include "chromeos/ash/components/login/auth/auth_performer.h"
#include "chromeos/ash/components/login/auth/public/auth_session_intent.h"
#include "chromeos/ash/components/login/auth/public/authentication_error.h"
#include "chromeos/ash/components/login/auth/public/cryptohome_key_constants.h"
#include "chromeos/ash/components/login/auth/public/user_context.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_types.h"
#include "ui/display/screen.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/layout/layout_types.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"

namespace ash {

namespace {

void AddMargins(views::View* view) {
  const auto* layout_provider = views::LayoutProvider::Get();
  const int horizontal_spacing = layout_provider->GetDistanceMetric(
      views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
  const int vertical_spacing = layout_provider->GetDistanceMetric(
      views::DISTANCE_RELATED_CONTROL_VERTICAL);

  view->SetProperty(views::kMarginsKey,
                    gfx::Insets::VH(vertical_spacing, horizontal_spacing));
}

void ConfigurePasswordField(views::Textfield* password_field) {
  const auto password_field_name =
      l10n_util::GetStringUTF16(IDS_ASH_LOGIN_POD_PASSWORD_PLACEHOLDER);
  password_field->SetAccessibleName(password_field_name);
  password_field->SetReadOnly(false);
  password_field->SetTextInputType(ui::TextInputType::TEXT_INPUT_TYPE_PASSWORD);
  password_field->SetPlaceholderText(password_field_name);
  AddMargins(password_field);
}

void ConfigureInvalidPasswordLabel(views::Label* invalid_password_label) {
  invalid_password_label->SetProperty(views::kCrossAxisAlignmentKey,
                                      views::LayoutAlignment::kStart);
  invalid_password_label->SetEnabledColor(SK_ColorRED);
  AddMargins(invalid_password_label);
}

void CenterWidgetOnPrimaryDisplay(views::Widget* widget) {
  auto bounds = display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
  bounds.ClampToCenteredSize(widget->GetContentsView()->GetPreferredSize());
  widget->SetBounds(bounds);
}

}  // namespace

AuthenticationDialog::AuthenticationDialog(
    InSessionAuthDialogController::OnAuthComplete on_auth_complete,
    InSessionAuthTokenProvider* auth_token_provider,
    std::unique_ptr<AuthPerformer> auth_performer,
    const AccountId& account_id)
    : password_field_(AddChildView(std::make_unique<views::Textfield>())),
      invalid_password_label_(AddChildView(std::make_unique<views::Label>())),
      on_auth_complete_(std::move(on_auth_complete)),
      auth_performer_(std::move(auth_performer)),
      auth_token_provider_(auth_token_provider) {
  // Dialog setup
  set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
      views::DistanceMetric::DISTANCE_BUBBLE_PREFERRED_WIDTH));
  SetTitle(l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_TITLE));
  SetModalType(ui::MODAL_TYPE_SYSTEM);

  // Callback setup
  SetCancelCallback(base::BindOnce(&AuthenticationDialog::CancelAuthAttempt,
                                   base::Unretained(this)));
  SetCloseCallback(base::BindOnce(&AuthenticationDialog::CancelAuthAttempt,
                                  base::Unretained(this)));

  SetLayoutManager(std::make_unique<views::FlexLayout>())
      ->SetOrientation(views::LayoutOrientation::kVertical)
      .SetCollapseMargins(true);

  ConfigureChildViews();

  // We don't want the user to submit an auth factor to cryptohome before the
  // auth session has started. We re-enable the UI in `OnAuthSessionStarted`
  SetUIDisabled(true);

  auto user_context = std::make_unique<UserContext>();
  user_context->SetAccountId(account_id);

  // TODO(b/240147756): Choose the intent based on
  // `InSessionAuthDialogController::Reason`.
  auth_performer_->StartAuthSession(
      std::move(user_context), /*ephemeral=*/false, AuthSessionIntent::kDecrypt,
      base::BindOnce(&AuthenticationDialog::OnAuthSessionStarted,
                     weak_factory_.GetWeakPtr()));
}

AuthenticationDialog::~AuthenticationDialog() = default;

void AuthenticationDialog::Show() {
  auto* widget = DialogDelegateView::CreateDialogWidget(this,
                                                        /*context=*/nullptr,
                                                        /*parent=*/nullptr);
  CenterWidgetOnPrimaryDisplay(widget);
  Init();
  widget->Show();
}

void AuthenticationDialog::Init() {
  ConfigureOkButton();
  password_field_->RequestFocus();
}

void AuthenticationDialog::NotifyResult(bool success,
                                        const base::UnguessableToken& token,
                                        base::TimeDelta timeout) {
  if (on_auth_complete_) {
    std::move(on_auth_complete_).Run(success, token, timeout);
  }
}

void AuthenticationDialog::ConfigureOkButton() {
  views::LabelButton* ok_button = GetOkButton();
  ok_button->SetText(
      l10n_util::GetStringUTF16(IDS_ASH_LOGIN_SUBMIT_BUTTON_ACCESSIBLE_NAME));
  ok_button->SetCallback(base::BindRepeating(
      &AuthenticationDialog::ValidateAuthFactor, weak_factory_.GetWeakPtr()));
}

void AuthenticationDialog::SetUIDisabled(bool is_disabled) {
  SetButtonEnabled(ui::DialogButton::DIALOG_BUTTON_OK, !is_disabled);
  SetButtonEnabled(ui::DialogButton::DIALOG_BUTTON_CANCEL, !is_disabled);
  password_field_->SetReadOnly(is_disabled);
}

void AuthenticationDialog::ValidateAuthFactor() {
  // Clear warning message.
  invalid_password_label_->SetText({});

  SetUIDisabled(true);

  cryptohome::KeyLabel key_label;

  if (features::IsUseAuthFactorsEnabled()) {
    key_label = user_context_->GetAuthFactorsData()
                    .FindOnlinePasswordFactor()
                    ->ref()
                    .label();
  } else {
    key_label =
        user_context_->GetAuthFactorsData().FindOnlinePasswordKey()->label;
  }

  // Create a copy of `user_context_` so that we don't lose it to std::move
  // for future auth attempts
  auth_performer_->AuthenticateWithPassword(
      key_label.value(), base::UTF16ToUTF8(password_field_->GetText()),
      std::make_unique<UserContext>(*user_context_),
      base::BindOnce(&AuthenticationDialog::OnAuthFactorValidityChecked,
                     weak_factory_.GetWeakPtr()));
}

void AuthenticationDialog::OnAuthFactorValidityChecked(
    std::unique_ptr<UserContext> user_context,
    absl::optional<AuthenticationError> authentication_error) {
  if (authentication_error.has_value()) {
    if (authentication_error.value().get_cryptohome_code() ==
        user_data_auth::CRYPTOHOME_INVALID_AUTH_SESSION_TOKEN) {
      // Auth session expired for some reason, start it again and reattempt
      // authentication.
      // TODO(b/240147756): Choose the intent based on
      // `InSessionAuthDialogController::Reason`.
      auth_performer_->StartAuthSession(
          std::move(user_context), /*ephemeral=*/false,
          AuthSessionIntent::kDecrypt,
          base::BindOnce(&AuthenticationDialog::OnAuthSessionInvalid,
                         weak_factory_.GetWeakPtr()));
      return;
    }
    LOG(ERROR) << "An error happened during the attempt to validate"
                  "the password: "
               << authentication_error.value().get_cryptohome_code();
    password_field_->SetInvalid(true);
    password_field_->SelectAll(false);
    invalid_password_label_->SetText(
        l10n_util::GetStringUTF16(IDS_ASH_LOGIN_ERROR_AUTHENTICATING));
    SetUIDisabled(false);
    return;
  }

  is_closing_ = true;

  auth_token_provider_->ExchangeForToken(
      std::move(user_context),
      base::BindOnce(&AuthenticationDialog::NotifyResult,
                     weak_factory_.GetWeakPtr(), /*success=*/true));

  SetUIDisabled(false);
  CancelDialog();
  return;
}

void AuthenticationDialog::CancelAuthAttempt() {
  // If dialog is closing after the submission of a valid auth factor,
  // we should not notify any parties, as they would have already been
  // notified after `AuthenticationDialog::OnAuthFactorValidityChecked`
  if (!is_closing_) {
    NotifyResult(/*success=*/false, /*token=*/{}, /*timeout=*/{});
  }
}

void AuthenticationDialog::ConfigureChildViews() {
  ConfigurePasswordField(password_field_);
  ConfigureInvalidPasswordLabel(invalid_password_label_);
}

void AuthenticationDialog::OnAuthSessionInvalid(
    bool user_exists,
    std::unique_ptr<UserContext> user_context,
    absl::optional<AuthenticationError> authentication_error) {
  OnAuthSessionStarted(user_exists, std::move(user_context),
                       authentication_error);
  ValidateAuthFactor();
}

void AuthenticationDialog::OnAuthSessionStarted(
    bool user_exists,
    std::unique_ptr<UserContext> user_context,
    absl::optional<AuthenticationError> authentication_error) {
  if (authentication_error.has_value()) {
    LOG(ERROR) << "Error starting authsession for in session authentication: "
               << authentication_error.value().get_cryptohome_code();
    CancelAuthAttempt();
  } else if (!user_exists) {
    LOG(ERROR) << "Attempting to authenticate a user which does not exist. "
                  "Aborting authentication attempt";
    CancelAuthAttempt();
  } else {
    user_context_ = std::move(user_context);
    SetUIDisabled(false);
  }
}

}  // namespace ash
