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

#include "components/signin/public/identity_manager/test_identity_manager_observer.h"

#include <utility>

#include "testing/gtest/include/gtest/gtest.h"

namespace signin {

TestIdentityManagerObserver::TestIdentityManagerObserver(
    IdentityManager* identity_manager)
    : identity_manager_(identity_manager) {
  identity_manager_->AddObserver(this);
}

TestIdentityManagerObserver::~TestIdentityManagerObserver() {
  identity_manager_->RemoveObserver(this);
}

void TestIdentityManagerObserver::SetOnPrimaryAccountChangedCallback(
    PrimaryAccountChangedCallback callback) {
  on_primary_account_changed_callback_ = std::move(callback);
}

const PrimaryAccountChangeEvent&
TestIdentityManagerObserver::GetPrimaryAccountChangedEvent() {
  return on_primary_account_changed_event_;
}

void TestIdentityManagerObserver::SetOnRefreshTokenUpdatedCallback(
    base::OnceClosure callback) {
  on_refresh_token_updated_callback_ = std::move(callback);
}

const CoreAccountInfo&
TestIdentityManagerObserver::AccountFromRefreshTokenUpdatedCallback() {
  return account_from_refresh_token_updated_callback_;
}

void TestIdentityManagerObserver::SetOnErrorStateOfRefreshTokenUpdatedCallback(
    base::OnceClosure callback) {
  on_error_state_of_refresh_token_updated_callback_ = std::move(callback);
}

const CoreAccountInfo& TestIdentityManagerObserver::
    AccountFromErrorStateOfRefreshTokenUpdatedCallback() {
  return account_from_error_state_of_refresh_token_updated_callback_;
}

const GoogleServiceAuthError&
TestIdentityManagerObserver::ErrorFromErrorStateOfRefreshTokenUpdatedCallback()
    const {
  return error_from_error_state_of_refresh_token_updated_callback_;
}

signin_metrics::SourceForRefreshTokenOperation TestIdentityManagerObserver::
    TokenOperationSourceFromErrorStateOfRefreshTokenUpdatedCallback() const {
  return token_operation_source_from_error_state_of_refresh_token_updated_callback_;
}

void TestIdentityManagerObserver::SetOnRefreshTokenRemovedCallback(
    base::OnceClosure callback) {
  on_refresh_token_removed_callback_ = std::move(callback);
}

const CoreAccountId&
TestIdentityManagerObserver::AccountIdFromRefreshTokenRemovedCallback() {
  return account_from_refresh_token_removed_callback_;
}

void TestIdentityManagerObserver::SetOnRefreshTokensLoadedCallback(
    base::OnceClosure callback) {
  on_refresh_tokens_loaded_callback_ = std::move(callback);
}

void TestIdentityManagerObserver::SetOnAccountsInCookieUpdatedCallback(
    base::OnceClosure callback) {
  on_accounts_in_cookie_updated_callback_ = std::move(callback);
}

const AccountsInCookieJarInfo&
TestIdentityManagerObserver::AccountsInfoFromAccountsInCookieUpdatedCallback() {
  return accounts_info_from_cookie_change_callback_;
}

const GoogleServiceAuthError&
TestIdentityManagerObserver::ErrorFromAccountsInCookieUpdatedCallback() const {
  return error_from_cookie_change_callback_;
}

void TestIdentityManagerObserver::SetOnCookieDeletedByUserCallback(
    base::OnceClosure callback) {
  on_cookie_deleted_by_user_callback_ = std::move(callback);
}

const AccountInfo&
TestIdentityManagerObserver::AccountFromAccountUpdatedCallback() {
  return account_from_account_updated_callback_;
}

const AccountInfo&
TestIdentityManagerObserver::AccountFromAccountRemovedWithInfoCallback() {
  return account_from_account_removed_with_info_callback_;
}

bool TestIdentityManagerObserver::WasCalledAccountRemovedWithInfoCallback() {
  return was_called_account_removed_with_info_callback_;
}

// Each element represents all the changes from an individual batch that has
// occurred, with the elements ordered from oldest to newest batch occurrence.
const std::vector<std::vector<CoreAccountId>>&
TestIdentityManagerObserver::BatchChangeRecords() const {
  return batch_change_records_;
}

#if BUILDFLAG(IS_IOS)
size_t
TestIdentityManagerObserver::GetOnEndBatchOfPrimaryAccountChangesCalledCount()
    const {
  return on_end_batch_of_primary_account_changes_called_count_;
}
#endif  // BUILDFLAG(IS_IOS)

// IdentityManager::Observer:
void TestIdentityManagerObserver::OnPrimaryAccountChanged(
    const PrimaryAccountChangeEvent& event) {
  on_primary_account_changed_event_ = event;
  if (on_primary_account_changed_callback_) {
    std::move(on_primary_account_changed_callback_).Run(event);
  }
}

void TestIdentityManagerObserver::OnRefreshTokenUpdatedForAccount(
    const CoreAccountInfo& account_info) {
  if (!is_inside_batch_) {
    StartBatchOfRefreshTokenStateChanges();
  }

  batch_change_records_.rbegin()->emplace_back(account_info.account_id);
  account_from_refresh_token_updated_callback_ = account_info;
  if (on_refresh_token_updated_callback_) {
    std::move(on_refresh_token_updated_callback_).Run();
  }
}

void TestIdentityManagerObserver::OnRefreshTokenRemovedForAccount(
    const CoreAccountId& account_id) {
  if (!is_inside_batch_) {
    StartBatchOfRefreshTokenStateChanges();
  }

  batch_change_records_.rbegin()->emplace_back(account_id);
  account_from_refresh_token_removed_callback_ = account_id;
  if (on_refresh_token_removed_callback_) {
    std::move(on_refresh_token_removed_callback_).Run();
  }
}

void TestIdentityManagerObserver::OnErrorStateOfRefreshTokenUpdatedForAccount(
    const CoreAccountInfo& account_info,
    const GoogleServiceAuthError& error,
    signin_metrics::SourceForRefreshTokenOperation token_operation_source) {
  account_from_error_state_of_refresh_token_updated_callback_ = account_info;
  error_from_error_state_of_refresh_token_updated_callback_ = error;
  token_operation_source_from_error_state_of_refresh_token_updated_callback_ =
      token_operation_source;
  if (on_error_state_of_refresh_token_updated_callback_) {
    std::move(on_error_state_of_refresh_token_updated_callback_).Run();
  }
}

void TestIdentityManagerObserver::OnRefreshTokensLoaded() {
  if (on_refresh_tokens_loaded_callback_) {
    std::move(on_refresh_tokens_loaded_callback_).Run();
  }
}

void TestIdentityManagerObserver::OnAccountsInCookieUpdated(
    const AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
    const GoogleServiceAuthError& error) {
  accounts_info_from_cookie_change_callback_ = accounts_in_cookie_jar_info;
  error_from_cookie_change_callback_ = error;
  if (on_accounts_in_cookie_updated_callback_) {
    std::move(on_accounts_in_cookie_updated_callback_).Run();
  }
}

void TestIdentityManagerObserver::OnAccountsCookieDeletedByUserAction() {
  std::move(on_cookie_deleted_by_user_callback_).Run();
}

void TestIdentityManagerObserver::OnExtendedAccountInfoUpdated(
    const AccountInfo& info) {
  account_from_account_updated_callback_ = info;
}

void TestIdentityManagerObserver::OnExtendedAccountInfoRemoved(
    const AccountInfo& info) {
  was_called_account_removed_with_info_callback_ = true;
  account_from_account_removed_with_info_callback_ = info;
}

#if BUILDFLAG(IS_IOS)
void TestIdentityManagerObserver::OnEndBatchOfPrimaryAccountChanges() {
  ++on_end_batch_of_primary_account_changes_called_count_;
}
#endif  // BUILDFLAG(IS_IOS)

void TestIdentityManagerObserver::StartBatchOfRefreshTokenStateChanges() {
  EXPECT_FALSE(is_inside_batch_);
  is_inside_batch_ = true;

  // Start a new batch.
  batch_change_records_.emplace_back(std::vector<CoreAccountId>());
}

void TestIdentityManagerObserver::OnEndBatchOfRefreshTokenStateChanges() {
  is_inside_batch_ = false;
}

}  // namespace signin
