// 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 "components/gcm_driver/gcm_account_mapper.h"

#include <utility>

#include "base/bind.h"
#include "base/guid.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "components/gcm_driver/gcm_driver_desktop.h"
#include "google_apis/gcm/engine/gcm_store.h"

namespace gcm {

namespace {

const char kGCMAccountMapperSenderId[] = "745476177629";
const char kGCMAccountMapperSendTo[] = "google.com";
const int kGCMAddMappingMessageTTL = 30 * 60;  // 0.5 hours in seconds.
const int kGCMRemoveMappingMessageTTL = 24 * 60 * 60;  // 1 day in seconds.
const int kGCMUpdateIntervalHours = 24;
// Because adding an account mapping dependents on a fresh OAuth2 token, we
// allow the update to happen earlier than update due time, if it is within
// the early start time to take advantage of that token.
const int kGCMUpdateEarlyStartHours = 6;
const char kRegistrationIdMessgaeKey[] = "id";
const char kTokenMessageKey[] = "t";
const char kAccountMessageKey[] = "a";
const char kRemoveAccountKey[] = "r";
const char kRemoveAccountValue[] = "1";
// Use to handle send to Gaia ID scenario:
const char kGCMSendToGaiaIdAppIdKey[] = "gcmb";


std::string GenerateMessageID() {
  return base::GenerateGUID();
}

}  // namespace

const char kGCMAccountMapperAppId[] = "com.google.android.gms";

GCMAccountMapper::GCMAccountMapper(GCMDriver* gcm_driver)
    : gcm_driver_(gcm_driver),
      clock_(base::DefaultClock::GetInstance()),
      initialized_(false),
      weak_ptr_factory_(this) {}

GCMAccountMapper::~GCMAccountMapper() {
}

void GCMAccountMapper::Initialize(const AccountMappings& account_mappings,
                                  const DispatchMessageCallback& callback) {
  DCHECK(!initialized_);
  initialized_ = true;
  accounts_ = account_mappings;
  dispatch_message_callback_ = callback;
  GetRegistration();
}

void GCMAccountMapper::SetAccountTokens(
    const std::vector<GCMClient::AccountTokenInfo>& account_tokens) {
  DVLOG(1) << "GCMAccountMapper::SetAccountTokens called with "
           << account_tokens.size() << " accounts.";

  // If account mapper is not ready to handle tasks yet, save the latest
  // account tokens and return.
  if (!IsReady()) {
    pending_account_tokens_ = account_tokens;
    // If mapper is initialized, but still does not have registration ID,
    // maybe the registration gave up. Retrying in case.
    if (initialized_ && gcm_driver_->IsStarted())
      GetRegistration();
    return;
  }

  // Start from removing the old tokens, from all of the known accounts.
  for (AccountMappings::iterator iter = accounts_.begin();
       iter != accounts_.end();
       ++iter) {
    iter->access_token.clear();
  }

  // Update the internal collection of mappings with the new tokens.
  for (std::vector<GCMClient::AccountTokenInfo>::const_iterator token_iter =
           account_tokens.begin();
       token_iter != account_tokens.end();
       ++token_iter) {
    AccountMapping* account_mapping =
        FindMappingByAccountId(token_iter->account_id);
    if (!account_mapping) {
      AccountMapping new_mapping;
      new_mapping.status = AccountMapping::NEW;
      new_mapping.account_id = token_iter->account_id;
      new_mapping.access_token = token_iter->access_token;
      new_mapping.email = token_iter->email;
      accounts_.push_back(new_mapping);
    } else {
      // Since we got a token for an account, drop the remove message and treat
      // it as mapped.
      if (account_mapping->status == AccountMapping::REMOVING) {
        account_mapping->status = AccountMapping::MAPPED;
        account_mapping->status_change_timestamp = base::Time();
        account_mapping->last_message_id.clear();
      }

      account_mapping->email = token_iter->email;
      account_mapping->access_token = token_iter->access_token;
    }
  }

  // Decide what to do with each account (either start mapping, or start
  // removing).
  for (AccountMappings::iterator mappings_iter = accounts_.begin();
       mappings_iter != accounts_.end();
       ++mappings_iter) {
    if (mappings_iter->access_token.empty()) {
      // Send a remove message if the account was not previously being removed,
      // or it doesn't have a pending message, or the pending message is
      // already expired, but OnSendError event was lost.
      if (mappings_iter->status != AccountMapping::REMOVING ||
          mappings_iter->last_message_id.empty() ||
          IsLastStatusChangeOlderThanTTL(*mappings_iter)) {
        SendRemoveMappingMessage(*mappings_iter);
      }
    } else {
      // A message is sent for all of the mappings considered NEW, or mappings
      // that are ADDING, but have expired message (OnSendError event lost), or
      // for those mapped accounts that can be refreshed.
      if (mappings_iter->status == AccountMapping::NEW ||
          (mappings_iter->status == AccountMapping::ADDING &&
           IsLastStatusChangeOlderThanTTL(*mappings_iter)) ||
          (mappings_iter->status == AccountMapping::MAPPED &&
           CanTriggerUpdate(mappings_iter->status_change_timestamp))) {
        mappings_iter->last_message_id.clear();
        SendAddMappingMessage(*mappings_iter);
      }
    }
  }
}

void GCMAccountMapper::ShutdownHandler() {
  initialized_ = false;
  accounts_.clear();
  registration_id_.clear();
  dispatch_message_callback_.Reset();
}

void GCMAccountMapper::OnStoreReset() {
  // TODO(crbug.com/661660): Tell server to remove the mapping. But can't use
  // upstream GCM send for that since the store got reset.
  ShutdownHandler();
}

void GCMAccountMapper::OnMessage(const std::string& app_id,
                                 const IncomingMessage& message) {
  DCHECK_EQ(app_id, kGCMAccountMapperAppId);
  // TODO(fgorski): Report Send to Gaia ID failures using UMA.

  if (dispatch_message_callback_.is_null()) {
    DVLOG(1) << "dispatch_message_callback_ missing in GCMAccountMapper";
    return;
  }

  MessageData::const_iterator it = message.data.find(kGCMSendToGaiaIdAppIdKey);
  if (it == message.data.end()) {
    DVLOG(1) << "Send to Gaia ID failure: Embedded app ID missing.";
    return;
  }

  std::string embedded_app_id = it->second;
  if (embedded_app_id.empty()) {
    DVLOG(1) << "Send to Gaia ID failure: Embedded app ID is empty.";
    return;
  }

  // Ensuring the message does not carry the embedded app ID.
  IncomingMessage new_message = message;
  new_message.data.erase(new_message.data.find(kGCMSendToGaiaIdAppIdKey));
  dispatch_message_callback_.Run(embedded_app_id, new_message);
}

void GCMAccountMapper::OnMessagesDeleted(const std::string& app_id) {
  // Account message does not expect messages right now.
}

void GCMAccountMapper::OnSendError(
    const std::string& app_id,
    const GCMClient::SendErrorDetails& send_error_details) {
  DCHECK_EQ(app_id, kGCMAccountMapperAppId);

  AccountMappings::iterator account_mapping_it =
      FindMappingByMessageId(send_error_details.message_id);

  if (account_mapping_it == accounts_.end())
    return;

  if (send_error_details.result != GCMClient::TTL_EXCEEDED) {
    DVLOG(1) << "Send error result different than TTL EXCEEDED: "
             << send_error_details.result << ". "
             << "Postponing the retry until a new batch of tokens arrives.";
    return;
  }

  if (account_mapping_it->status == AccountMapping::REMOVING) {
    // Another message to remove mapping can be sent immediately, because TTL
    // for those is one day. No need to back off.
    SendRemoveMappingMessage(*account_mapping_it);
  } else {
    if (account_mapping_it->status == AccountMapping::ADDING) {
      // There is no mapping established, so we can remove the entry.
      // Getting a fresh token will trigger a new attempt.
      gcm_driver_->RemoveAccountMapping(account_mapping_it->account_id);
      accounts_.erase(account_mapping_it);
    } else {
      // Account is already MAPPED, we have to wait for another token.
      account_mapping_it->last_message_id.clear();
      gcm_driver_->UpdateAccountMapping(*account_mapping_it);
    }
  }
}

void GCMAccountMapper::OnSendAcknowledged(const std::string& app_id,
                                          const std::string& message_id) {
  DCHECK_EQ(app_id, kGCMAccountMapperAppId);
  AccountMappings::iterator account_mapping_it =
      FindMappingByMessageId(message_id);

  DVLOG(1) << "OnSendAcknowledged with message ID: " << message_id;

  if (account_mapping_it == accounts_.end())
    return;

  // Here is where we advance a status of a mapping and persist or remove.
  if (account_mapping_it->status == AccountMapping::REMOVING) {
    // Message removing the account has been confirmed by the GCM, we can remove
    // all the information related to the account (from memory and store).
    gcm_driver_->RemoveAccountMapping(account_mapping_it->account_id);
    accounts_.erase(account_mapping_it);
  } else {
    // Mapping status is ADDING only when it is a first time mapping.
    DCHECK(account_mapping_it->status == AccountMapping::ADDING ||
           account_mapping_it->status == AccountMapping::MAPPED);

    // Account is marked as mapped with the current time.
    account_mapping_it->status = AccountMapping::MAPPED;
    account_mapping_it->status_change_timestamp = clock_->Now();
    // There is no pending message for the account.
    account_mapping_it->last_message_id.clear();

    gcm_driver_->UpdateAccountMapping(*account_mapping_it);
  }
}

bool GCMAccountMapper::CanHandle(const std::string& app_id) const {
  return app_id.compare(kGCMAccountMapperAppId) == 0;
}

bool GCMAccountMapper::IsReady() {
  return initialized_ && gcm_driver_->IsStarted() && !registration_id_.empty();
}

void GCMAccountMapper::SendAddMappingMessage(AccountMapping& account_mapping) {
  CreateAndSendMessage(account_mapping);
}

void GCMAccountMapper::SendRemoveMappingMessage(
    AccountMapping& account_mapping) {
  // We want to persist an account that is being removed as quickly as possible
  // as well as clean up the last message information.
  if (account_mapping.status != AccountMapping::REMOVING) {
    account_mapping.status = AccountMapping::REMOVING;
    account_mapping.status_change_timestamp = clock_->Now();
  }

  account_mapping.last_message_id.clear();

  gcm_driver_->UpdateAccountMapping(account_mapping);

  CreateAndSendMessage(account_mapping);
}

void GCMAccountMapper::CreateAndSendMessage(
    const AccountMapping& account_mapping) {
  OutgoingMessage outgoing_message;
  outgoing_message.id = GenerateMessageID();
  outgoing_message.data[kRegistrationIdMessgaeKey] = registration_id_;
  outgoing_message.data[kAccountMessageKey] = account_mapping.email;

  if (account_mapping.status == AccountMapping::REMOVING) {
    outgoing_message.time_to_live = kGCMRemoveMappingMessageTTL;
    outgoing_message.data[kRemoveAccountKey] = kRemoveAccountValue;
  } else {
    outgoing_message.data[kTokenMessageKey] = account_mapping.access_token;
    outgoing_message.time_to_live = kGCMAddMappingMessageTTL;
  }

  gcm_driver_->Send(kGCMAccountMapperAppId,
                    kGCMAccountMapperSendTo,
                    outgoing_message,
                    base::Bind(&GCMAccountMapper::OnSendFinished,
                               weak_ptr_factory_.GetWeakPtr(),
                               account_mapping.account_id));
}

void GCMAccountMapper::OnSendFinished(const std::string& account_id,
                                      const std::string& message_id,
                                      GCMClient::Result result) {
  // TODO(fgorski): Add another attempt, in case the QUEUE is not full.
  if (result != GCMClient::SUCCESS)
    return;

  AccountMapping* account_mapping = FindMappingByAccountId(account_id);
  DCHECK(account_mapping);

  // If we are dealing with account with status NEW, it is the first time
  // mapping, and we should mark it as ADDING.
  if (account_mapping->status == AccountMapping::NEW) {
    account_mapping->status = AccountMapping::ADDING;
    account_mapping->status_change_timestamp = clock_->Now();
  }

  account_mapping->last_message_id = message_id;

  gcm_driver_->UpdateAccountMapping(*account_mapping);
}

void GCMAccountMapper::GetRegistration() {
  DCHECK(registration_id_.empty());
  std::vector<std::string> sender_ids;
  sender_ids.push_back(kGCMAccountMapperSenderId);
  gcm_driver_->Register(kGCMAccountMapperAppId,
                        sender_ids,
                        base::Bind(&GCMAccountMapper::OnRegisterFinished,
                                   weak_ptr_factory_.GetWeakPtr()));
}

void GCMAccountMapper::OnRegisterFinished(const std::string& registration_id,
                                          GCMClient::Result result) {
  if (result == GCMClient::SUCCESS)
    registration_id_ = registration_id;

  if (IsReady()) {
    if (!pending_account_tokens_.empty()) {
      SetAccountTokens(pending_account_tokens_);
      pending_account_tokens_.clear();
    }
  }
}

bool GCMAccountMapper::CanTriggerUpdate(
    const base::Time& last_update_time) const {
  return last_update_time +
             base::TimeDelta::FromHours(kGCMUpdateIntervalHours -
                                        kGCMUpdateEarlyStartHours) <
         clock_->Now();
}

bool GCMAccountMapper::IsLastStatusChangeOlderThanTTL(
    const AccountMapping& account_mapping) const {
  int ttl_seconds = account_mapping.status == AccountMapping::REMOVING ?
      kGCMRemoveMappingMessageTTL : kGCMAddMappingMessageTTL;
  return account_mapping.status_change_timestamp +
      base::TimeDelta::FromSeconds(ttl_seconds) < clock_->Now();
}

AccountMapping* GCMAccountMapper::FindMappingByAccountId(
    const std::string& account_id) {
  for (AccountMappings::iterator iter = accounts_.begin();
       iter != accounts_.end();
       ++iter) {
    if (iter->account_id == account_id)
      return &*iter;
  }

  return nullptr;
}

GCMAccountMapper::AccountMappings::iterator
GCMAccountMapper::FindMappingByMessageId(const std::string& message_id) {
  for (std::vector<AccountMapping>::iterator iter = accounts_.begin();
       iter != accounts_.end();
       ++iter) {
    if (iter->last_message_id == message_id)
      return iter;
  }

  return accounts_.end();
}

void GCMAccountMapper::SetClockForTesting(base::Clock* clock) {
  clock_ = clock;
}

}  // namespace gcm
