// Copyright 2014 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 "google_apis/gaia/account_tracker.h"

#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/profiler/scoped_tracker.h"
#include "base/stl_util.h"
#include "net/url_request/url_request_context_getter.h"

namespace gaia {

AccountTracker::AccountTracker(
    IdentityProvider* identity_provider,
    net::URLRequestContextGetter* request_context_getter)
    : identity_provider_(identity_provider),
      request_context_getter_(request_context_getter),
      shutdown_called_(false) {
  identity_provider_->AddObserver(this);
  identity_provider_->GetTokenService()->AddObserver(this);
}

AccountTracker::~AccountTracker() {
  DCHECK(shutdown_called_);
}

void AccountTracker::Shutdown() {
  shutdown_called_ = true;
  STLDeleteValues(&user_info_requests_);
  identity_provider_->GetTokenService()->RemoveObserver(this);
  identity_provider_->RemoveObserver(this);
}

bool AccountTracker::IsAllUserInfoFetched() const {
  return user_info_requests_.empty();
}

void AccountTracker::AddObserver(Observer* observer) {
  observer_list_.AddObserver(observer);
}

void AccountTracker::RemoveObserver(Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

std::vector<AccountIds> AccountTracker::GetAccounts() const {
  const std::string active_account_id =
      identity_provider_->GetActiveAccountId();
  std::vector<AccountIds> accounts;

  for (std::map<std::string, AccountState>::const_iterator it =
           accounts_.begin();
       it != accounts_.end();
       ++it) {
    const AccountState& state = it->second;
    bool is_visible = state.is_signed_in && !state.ids.gaia.empty();

    if (it->first == active_account_id) {
      if (is_visible)
        accounts.insert(accounts.begin(), state.ids);
      else
        return std::vector<AccountIds>();

    } else if (is_visible) {
      accounts.push_back(state.ids);
    }
  }
  return accounts;
}

AccountIds AccountTracker::FindAccountIdsByGaiaId(const std::string& gaia_id) {
  for (std::map<std::string, AccountState>::const_iterator it =
           accounts_.begin();
       it != accounts_.end();
       ++it) {
    const AccountState& state = it->second;
    if (state.ids.gaia == gaia_id) {
      return state.ids;
    }
  }

  return AccountIds();
}

void AccountTracker::OnRefreshTokenAvailable(const std::string& account_id) {
  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "422460 AccountTracker::OnRefreshTokenAvailable"));

  TRACE_EVENT1("identity",
               "AccountTracker::OnRefreshTokenAvailable",
               "account_key",
               account_id);

  // Ignore refresh tokens if there is no active account ID at all.
  if (identity_provider_->GetActiveAccountId().empty())
    return;

  DVLOG(1) << "AVAILABLE " << account_id;
  UpdateSignInState(account_id, true);
}

void AccountTracker::OnRefreshTokenRevoked(const std::string& account_id) {
  TRACE_EVENT1("identity",
               "AccountTracker::OnRefreshTokenRevoked",
               "account_key",
               account_id);

  DVLOG(1) << "REVOKED " << account_id;
  UpdateSignInState(account_id, false);
}

void AccountTracker::OnActiveAccountLogin() {
  TRACE_EVENT0("identity", "AccountTracker::OnActiveAccountLogin");

  std::vector<std::string> accounts =
      identity_provider_->GetTokenService()->GetAccounts();

  DVLOG(1) << "LOGIN " << accounts.size() << " accounts available.";

  for (std::vector<std::string>::const_iterator it = accounts.begin();
       it != accounts.end();
       ++it) {
    OnRefreshTokenAvailable(*it);
  }
}

void AccountTracker::OnActiveAccountLogout() {
  TRACE_EVENT0("identity", "AccountTracker::OnActiveAccountLogout");
  DVLOG(1) << "LOGOUT";
  StopTrackingAllAccounts();
}

void AccountTracker::SetAccountStateForTest(AccountIds ids, bool is_signed_in) {
  accounts_[ids.account_key].ids = ids;
  accounts_[ids.account_key].is_signed_in = is_signed_in;

  DVLOG(1) << "SetAccountStateForTest " << ids.account_key << ":"
           << is_signed_in;

  if (VLOG_IS_ON(1)) {
    for (std::map<std::string, AccountState>::const_iterator it =
             accounts_.begin();
         it != accounts_.end();
         ++it) {
      DVLOG(1) << it->first << ":" << it->second.is_signed_in;
    }
  }
}

void AccountTracker::NotifyAccountAdded(const AccountState& account) {
  DCHECK(!account.ids.gaia.empty());
  FOR_EACH_OBSERVER(
      Observer, observer_list_, OnAccountAdded(account.ids));
}

void AccountTracker::NotifyAccountRemoved(const AccountState& account) {
  DCHECK(!account.ids.gaia.empty());
  FOR_EACH_OBSERVER(
      Observer, observer_list_, OnAccountRemoved(account.ids));
}

void AccountTracker::NotifySignInChanged(const AccountState& account) {
  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "422460 AccountTracker::NotifySignInChanged"));

  DCHECK(!account.ids.gaia.empty());
  FOR_EACH_OBSERVER(Observer,
                    observer_list_,
                    OnAccountSignInChanged(account.ids, account.is_signed_in));
}

void AccountTracker::UpdateSignInState(const std::string account_key,
                                       bool is_signed_in) {
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "422460 AccountTracker::UpdateSignInState"));

  StartTrackingAccount(account_key);
  AccountState& account = accounts_[account_key];
  bool needs_gaia_id = account.ids.gaia.empty();
  bool was_signed_in = account.is_signed_in;
  account.is_signed_in = is_signed_in;

  if (needs_gaia_id && is_signed_in)
    StartFetchingUserInfo(account_key);

  if (!needs_gaia_id && (was_signed_in != is_signed_in))
    NotifySignInChanged(account);
}

void AccountTracker::StartTrackingAccount(const std::string account_key) {
  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "422460 AccountTracker::StartTrackingAccount"));

  if (!ContainsKey(accounts_, account_key)) {
    DVLOG(1) << "StartTracking " << account_key;
    AccountState account_state;
    account_state.ids.account_key = account_key;
    account_state.ids.email = account_key;
    account_state.is_signed_in = false;
    accounts_.insert(make_pair(account_key, account_state));
  }
}

void AccountTracker::StopTrackingAccount(const std::string account_key) {
  DVLOG(1) << "StopTracking " << account_key;
  if (ContainsKey(accounts_, account_key)) {
    AccountState& account = accounts_[account_key];
    if (!account.ids.gaia.empty()) {
      UpdateSignInState(account_key, false);
      NotifyAccountRemoved(account);
    }
    accounts_.erase(account_key);
  }

  if (ContainsKey(user_info_requests_, account_key))
    DeleteFetcher(user_info_requests_[account_key]);
}

void AccountTracker::StopTrackingAllAccounts() {
  while (!accounts_.empty())
    StopTrackingAccount(accounts_.begin()->first);
}

void AccountTracker::StartFetchingUserInfo(const std::string account_key) {
  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
  tracked_objects::ScopedTracker tracking_profile(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "422460 AccountTracker::StartFetchingUserInfo"));

  if (ContainsKey(user_info_requests_, account_key)) {
    // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
    tracked_objects::ScopedTracker tracking_profile1(
        FROM_HERE_WITH_EXPLICIT_FUNCTION(
            "422460 AccountTracker::StartFetchingUserInfo 1"));

    DeleteFetcher(user_info_requests_[account_key]);
  }

  DVLOG(1) << "StartFetching " << account_key;
  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
  tracked_objects::ScopedTracker tracking_profile2(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "422460 AccountTracker::StartFetchingUserInfo 2"));

  AccountIdFetcher* fetcher =
      new AccountIdFetcher(identity_provider_->GetTokenService(),
                           request_context_getter_.get(),
                           this,
                           account_key);
  user_info_requests_[account_key] = fetcher;

  // TODO(vadimt): Remove ScopedTracker below once crbug.com/422460 is fixed.
  tracked_objects::ScopedTracker tracking_profile3(
      FROM_HERE_WITH_EXPLICIT_FUNCTION(
          "422460 AccountTracker::StartFetchingUserInfo 3"));

  fetcher->Start();
}

void AccountTracker::OnUserInfoFetchSuccess(AccountIdFetcher* fetcher,
                                            const std::string& gaia_id) {
  const std::string& account_key = fetcher->account_key();
  DCHECK(ContainsKey(accounts_, account_key));
  AccountState& account = accounts_[account_key];

  account.ids.gaia = gaia_id;
  NotifyAccountAdded(account);

  if (account.is_signed_in)
    NotifySignInChanged(account);

  DeleteFetcher(fetcher);
}

void AccountTracker::OnUserInfoFetchFailure(AccountIdFetcher* fetcher) {
  LOG(WARNING) << "Failed to get UserInfo for " << fetcher->account_key();
  std::string key = fetcher->account_key();
  DeleteFetcher(fetcher);
  StopTrackingAccount(key);
}

void AccountTracker::DeleteFetcher(AccountIdFetcher* fetcher) {
  DVLOG(1) << "DeleteFetcher " << fetcher->account_key();
  const std::string& account_key = fetcher->account_key();
  DCHECK(ContainsKey(user_info_requests_, account_key));
  DCHECK_EQ(fetcher, user_info_requests_[account_key]);
  user_info_requests_.erase(account_key);
  delete fetcher;
}

AccountIdFetcher::AccountIdFetcher(
    OAuth2TokenService* token_service,
    net::URLRequestContextGetter* request_context_getter,
    AccountTracker* tracker,
    const std::string& account_key)
    : OAuth2TokenService::Consumer("gaia_account_tracker"),
      token_service_(token_service),
      request_context_getter_(request_context_getter),
      tracker_(tracker),
      account_key_(account_key) {
  TRACE_EVENT_ASYNC_BEGIN1(
      "identity", "AccountIdFetcher", this, "account_key", account_key);
}

AccountIdFetcher::~AccountIdFetcher() {
  TRACE_EVENT_ASYNC_END0("identity", "AccountIdFetcher", this);
}

void AccountIdFetcher::Start() {
  OAuth2TokenService::ScopeSet scopes;
  scopes.insert("https://www.googleapis.com/auth/userinfo.profile");
  login_token_request_ = token_service_->StartRequest(
      account_key_, scopes, this);
}

void AccountIdFetcher::OnGetTokenSuccess(
    const OAuth2TokenService::Request* request,
    const std::string& access_token,
    const base::Time& expiration_time) {
  TRACE_EVENT_ASYNC_STEP_PAST0(
      "identity", "AccountIdFetcher", this, "OnGetTokenSuccess");
  DCHECK_EQ(request, login_token_request_.get());

  gaia_oauth_client_.reset(new gaia::GaiaOAuthClient(request_context_getter_));

  const int kMaxGetUserIdRetries = 3;
  gaia_oauth_client_->GetUserId(access_token, kMaxGetUserIdRetries, this);
}

void AccountIdFetcher::OnGetTokenFailure(
    const OAuth2TokenService::Request* request,
    const GoogleServiceAuthError& error) {
  TRACE_EVENT_ASYNC_STEP_PAST1("identity",
                               "AccountIdFetcher",
                               this,
                               "OnGetTokenFailure",
                               "google_service_auth_error",
                               error.ToString());
  LOG(ERROR) << "OnGetTokenFailure: " << error.ToString();
  DCHECK_EQ(request, login_token_request_.get());
  tracker_->OnUserInfoFetchFailure(this);
}

void AccountIdFetcher::OnGetUserIdResponse(const std::string& gaia_id) {
  TRACE_EVENT_ASYNC_STEP_PAST1("identity",
                               "AccountIdFetcher",
                               this,
                               "OnGetUserIdResponse",
                               "gaia_id",
                               gaia_id);
  tracker_->OnUserInfoFetchSuccess(this, gaia_id);
}

void AccountIdFetcher::OnOAuthError() {
  TRACE_EVENT_ASYNC_STEP_PAST0(
      "identity", "AccountIdFetcher", this, "OnOAuthError");
  LOG(ERROR) << "OnOAuthError";
  tracker_->OnUserInfoFetchFailure(this);
}

void AccountIdFetcher::OnNetworkError(int response_code) {
  TRACE_EVENT_ASYNC_STEP_PAST1("identity",
                               "AccountIdFetcher",
                               this,
                               "OnNetworkError",
                               "response_code",
                               response_code);
  LOG(ERROR) << "OnNetworkError " << response_code;
  tracker_->OnUserInfoFetchFailure(this);
}

}  // namespace gaia
