// Copyright 2015 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/autofill/core/browser/webdata/autofill_wallet_metadata_syncable_service.h"

#include <stddef.h>

#include <utility>

#include "base/base64.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/time/time.h"
#include "components/autofill/core/browser/autofill_data_model.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/webdata/autofill_change.h"
#include "components/autofill/core/browser/webdata/autofill_table.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_backend.h"
#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
#include "components/autofill/core/common/autofill_util.h"
#include "components/sync/model/sync_change.h"
#include "components/sync/model/sync_change_processor.h"
#include "components/sync/model/sync_data.h"
#include "components/sync/model/sync_error_factory.h"
#include "components/sync/protocol/sync.pb.h"

namespace autofill {

namespace {

void* AutofillWalletMetadataSyncableServiceUserDataKey() {
  // Use the address of a static so that COMDAT folding won't ever fold
  // with something else.
  static int user_data_key = 0;
  return reinterpret_cast<void*>(&user_data_key);
}

// Sets the common syncable |metadata| for the |local_data_model|.
void SetCommonMetadata(sync_pb::WalletMetadataSpecifics::Type type,
                       const std::string& server_id,
                       const AutofillDataModel& local_data_model,
                       sync_pb::WalletMetadataSpecifics* metadata) {
  metadata->set_type(type);
  metadata->set_id(server_id);
  metadata->set_use_count(local_data_model.use_count());
  metadata->set_use_date(local_data_model.use_date().ToInternalValue());
}

// Returns syncable metadata for the |local_profile|.
syncer::SyncData BuildSyncData(sync_pb::WalletMetadataSpecifics::Type type,
                               const std::string& server_id,
                               const AutofillProfile& local_profile) {
  sync_pb::EntitySpecifics entity;
  sync_pb::WalletMetadataSpecifics* metadata = entity.mutable_wallet_metadata();
  SetCommonMetadata(type, server_id, local_profile, metadata);
  metadata->set_address_has_converted(local_profile.has_converted());
  std::string sync_tag = "address-" + server_id;

  return syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity);
}

// Returns syncable metadata for the |local_card|.
syncer::SyncData BuildSyncData(sync_pb::WalletMetadataSpecifics::Type type,
                               const std::string& server_id,
                               const CreditCard& local_card) {
  sync_pb::EntitySpecifics entity;
  sync_pb::WalletMetadataSpecifics* metadata = entity.mutable_wallet_metadata();
  SetCommonMetadata(type, server_id, local_card, metadata);
  // The strings must be in valid UTF-8 to sync.
  std::string billing_address_id;
  base::Base64Encode(local_card.billing_address_id(), &billing_address_id);
  metadata->set_card_billing_address_id(billing_address_id);
  std::string sync_tag = "card-" + server_id;

  return syncer::SyncData::CreateLocalData(sync_tag, sync_tag, entity);
}

// If the metadata exists locally, undelete it on the sync server.
template <class DataType>
void UndeleteMetadataIfExisting(
    const std::string& server_id,
    const sync_pb::WalletMetadataSpecifics::Type& metadata_type,
    std::unordered_map<std::string, std::unique_ptr<DataType>>* locals,
    syncer::SyncChangeList* changes_to_sync) {
  const auto& it = locals->find(server_id);
  if (it != locals->end()) {
    std::unique_ptr<DataType> local_metadata = std::move(it->second);
    locals->erase(it);
    changes_to_sync->push_back(syncer::SyncChange(
        FROM_HERE, syncer::SyncChange::ACTION_ADD,
        BuildSyncData(metadata_type, server_id, *local_metadata)));
  }
}

syncer::SyncDataList::iterator FindServerIdAndTypeInCache(
    const std::string& server_id,
    const sync_pb::WalletMetadataSpecifics::Type& type,
    syncer::SyncDataList* cache) {
  for (auto it = cache->begin(); it != cache->end(); ++it) {
    if (server_id == it->GetSpecifics().wallet_metadata().id() &&
        type == it->GetSpecifics().wallet_metadata().type()) {
      return it;
    }
  }

  return cache->end();
}

syncer::SyncDataList::iterator FindItemInCache(const syncer::SyncData& item,
                                               syncer::SyncDataList* cache) {
  return FindServerIdAndTypeInCache(
      item.GetSpecifics().wallet_metadata().id(),
      item.GetSpecifics().wallet_metadata().type(), cache);
}

void RemoveItemFromCache(const syncer::SyncData& item,
                         syncer::SyncDataList* cache) {
  auto it = FindItemInCache(item, cache);
  if (it != cache->end())
    cache->erase(it);
}

void AddOrUpdateItemInCache(const syncer::SyncData& item,
                            syncer::SyncDataList* cache) {
  auto it = FindItemInCache(item, cache);
  if (it != cache->end())
    *it = item;
  else
    cache->push_back(item);
}

void ApplyChangesToCache(const syncer::SyncChangeList& changes,
                         syncer::SyncDataList* cache) {
  for (const syncer::SyncChange& change : changes) {
    switch (change.change_type()) {
      case syncer::SyncChange::ACTION_ADD:
      // Intentional fall through.
      case syncer::SyncChange::ACTION_UPDATE:
        AddOrUpdateItemInCache(change.sync_data(), cache);
        break;

      case syncer::SyncChange::ACTION_DELETE:
        RemoveItemFromCache(change.sync_data(), cache);
        break;

      case syncer::SyncChange::ACTION_INVALID:
        NOTREACHED();
        break;
    }
  }
}

template <class DataType>
bool AreLocalUseStatsUpdated(const sync_pb::WalletMetadataSpecifics& remote,
                             const DataType& local) {
  return base::checked_cast<size_t>(remote.use_count()) < local.use_count() &&
         base::Time::FromInternalValue(remote.use_date()) < local.use_date();
}

bool IsLocalBillingAddressUpdated(
    const sync_pb::WalletMetadataSpecifics& remote,
    const CreditCard& local) {
  std::string remote_billing_address_id;
  base::Base64Decode(remote.card_billing_address_id(),
                     &remote_billing_address_id);
  return local.billing_address_id() != remote_billing_address_id;
}

bool IsLocalHasConvertedStatusUpdated(
    const sync_pb::WalletMetadataSpecifics& remote,
    const AutofillProfile& local) {
  return remote.address_has_converted() != local.has_converted();
}

// Merges the metadata of the remote and local versions of the data model.
void MergeCommonMetadata(
    const sync_pb::WalletMetadataSpecifics& remote_metadata,
    AutofillDataModel* local_model,
    bool* is_remote_outdated,
    bool* is_local_modified) {
  size_t remote_use_count =
      base::checked_cast<size_t>(remote_metadata.use_count());
  base::Time remote_use_date =
      base::Time::FromInternalValue(remote_metadata.use_date());

  // If the two models have the same metadata, do nothing.
  if (local_model->use_count() == remote_use_count &&
      local_model->use_date() == remote_use_date) {
    return;
  }

  // Special case for local models with a use_count of one. This means the local
  // model was only created, never used. The remote model should always be
  // preferred.
  // This situation can happen for new Chromium instances where there is no data
  // yet on disk, making the use_date artifically high. Once the metadata sync
  // kicks in, we should use that value.
  if (local_model->use_count() == 1) {
    local_model->set_use_date(remote_use_date);
    local_model->set_use_count(remote_use_count);
    *is_local_modified = true;
  } else {
    // Otherwise, just keep the most recent use date and biggest use count.
    if (local_model->use_date() < remote_use_date) {
      local_model->set_use_date(remote_use_date);
      *is_local_modified = true;
    } else if (local_model->use_date() > remote_use_date) {
      *is_remote_outdated = true;
    }

    if (local_model->use_count() < remote_use_count) {
      local_model->set_use_count(remote_use_count);
      *is_local_modified = true;
    } else if (local_model->use_count() > remote_use_count) {
      *is_remote_outdated = true;
    }
  }
}

// Merges the metadata of the remote and local versions of the profile.
void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
                   AutofillProfile* local_profile,
                   bool* is_remote_outdated,
                   bool* is_local_modified) {
  // Merge the has_converted status.
  if (local_profile->has_converted() !=
      remote_metadata.address_has_converted()) {
    if (!local_profile->has_converted()) {
      local_profile->set_has_converted(true);
      *is_local_modified = true;
    } else {
      *is_remote_outdated = true;
    }
  }

  // Merge the use_count and use_date.
  MergeCommonMetadata(remote_metadata, local_profile, is_remote_outdated,
                      is_local_modified);
}

// Whether the |current_billing_address_id| is considered outdated compared to
// the |proposed_billing_address_id|.
bool IsBillingAddressOutdated(const std::string& current_billing_address_id,
                              const std::string& proposed_billing_address_id) {
  DCHECK(current_billing_address_id != proposed_billing_address_id);

  // If the current billing address is empty, or if the current one refers to a
  // server address and the proposed one refers to a local address, the current
  // billing address is considered outdated.
  return current_billing_address_id.empty() ||
         (current_billing_address_id.size() != kLocalGuidSize &&
          proposed_billing_address_id.size() == kLocalGuidSize);
}

// Merges the metadata of the remote and local versions of the credit card.
void MergeMetadata(const sync_pb::WalletMetadataSpecifics& remote_metadata,
                   CreditCard* local_card,
                   bool* is_remote_outdated,
                   bool* is_local_modified) {
  // Merge the billing_address_id. Do this before updating the use_count
  // because it may be used to determine what id to keep.
  std::string remote_billing_address_id;
  base::Base64Decode(remote_metadata.card_billing_address_id(),
                     &remote_billing_address_id);

  if (local_card->billing_address_id() != remote_billing_address_id) {
    if (IsBillingAddressOutdated(local_card->billing_address_id(),
                                 remote_billing_address_id)) {
      local_card->set_billing_address_id(remote_billing_address_id);
      *is_local_modified = true;
    } else if (IsBillingAddressOutdated(remote_billing_address_id,
                                        local_card->billing_address_id())) {
      *is_remote_outdated = true;
    } else {
      // The cards have a different non-empty billing address id and both refer
      // to the same type of address. Keep the billing address id of the most
      // recently used card. If both have the same timestamp, the remote version
      // should be kept in order to stabilize the values.
      base::Time remote_use_date =
          base::Time::FromInternalValue(remote_metadata.use_date());
      if (local_card->use_date() <= remote_use_date) {
        local_card->set_billing_address_id(remote_billing_address_id);
        *is_local_modified = true;
      } else {
        *is_remote_outdated = true;
      }
    }
  }

  // Merge the use_count and use_date.
  MergeCommonMetadata(remote_metadata, local_card, is_remote_outdated,
                      is_local_modified);
}

// Merges |remote| metadata into a collection of metadata |locals|. Returns true
// if the corresponding local metadata was found.
//
// Stores an "update" in |changes_to_sync| if |remote| corresponds to an item in
// |locals| that has higher use count and later use date.
template <class DataType>
bool MergeRemote(
    const syncer::SyncData& remote,
    const base::Callback<bool(const DataType&)>& updater,
    bool* is_any_local_modified,
    std::unordered_map<std::string, std::unique_ptr<DataType>>* locals,
    syncer::SyncChangeList* changes_to_sync) {
  DCHECK(locals);
  DCHECK(changes_to_sync);

  const sync_pb::WalletMetadataSpecifics& remote_metadata =
      remote.GetSpecifics().wallet_metadata();
  auto it = locals->find(remote_metadata.id());
  if (it == locals->end())
    return false;

  std::unique_ptr<DataType> local_metadata = std::move(it->second);
  locals->erase(it);

  bool is_local_modified = false;
  bool is_remote_outdated = false;
  MergeMetadata(remote_metadata, local_metadata.get(), &is_remote_outdated,
                &is_local_modified);

  if (is_remote_outdated) {
    changes_to_sync->push_back(syncer::SyncChange(
        FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
        BuildSyncData(remote_metadata.type(), remote_metadata.id(),
                      *local_metadata)));
  }

  if (is_local_modified) {
    updater.Run(*local_metadata);
    *is_any_local_modified = true;
  }

  return true;
}

template <typename DataType>
std::string GetServerId(const DataType& data) {
  std::string server_id;
  base::Base64Encode(data.server_id(), &server_id);
  return server_id;
}

}  // namespace

AutofillWalletMetadataSyncableService::
    ~AutofillWalletMetadataSyncableService() {}

void AutofillWalletMetadataSyncableService::OnWalletDataTrackingStateChanged(
    bool is_tracking) {
  DCHECK_NE(track_wallet_data_, is_tracking);
  track_wallet_data_ = is_tracking;
  if (is_tracking && sync_processor_) {
    MergeData(cache_);
  }
}

syncer::SyncMergeResult
AutofillWalletMetadataSyncableService::MergeDataAndStartSyncing(
    syncer::ModelType type,
    const syncer::SyncDataList& initial_sync_data,
    std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
    std::unique_ptr<syncer::SyncErrorFactory> sync_error_factory) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK(!sync_processor_);
  DCHECK(!sync_error_factory_);
  DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);

  sync_processor_ = std::move(sync_processor);
  sync_error_factory_ = std::move(sync_error_factory);

  cache_ = initial_sync_data;

  syncer::SyncMergeResult result(syncer::AUTOFILL_WALLET_METADATA);
  if (track_wallet_data_) {
    result = MergeData(initial_sync_data);
  }

  // Notify that sync has started. This callback does not currently take into
  // account whether we're actually tracking wallet data.
  if (web_data_backend_)
    web_data_backend_->NotifyThatSyncHasStarted(type);
  return result;
}

void AutofillWalletMetadataSyncableService::StopSyncing(
    syncer::ModelType type) {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);

  sync_processor_.reset();
  sync_error_factory_.reset();
  cache_.clear();
}

syncer::SyncDataList AutofillWalletMetadataSyncableService::GetAllSyncData(
    syncer::ModelType type) const {
  DCHECK(thread_checker_.CalledOnValidThread());
  DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, type);

  syncer::SyncDataList data_list;
  std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
  std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
  if (GetLocalData(&profiles, &cards)) {
    for (const auto& it : profiles) {
      data_list.push_back(BuildSyncData(
          sync_pb::WalletMetadataSpecifics::ADDRESS, it.first, *it.second));
    }

    for (const auto& it : cards) {
      data_list.push_back(BuildSyncData(sync_pb::WalletMetadataSpecifics::CARD,
                                        it.first, *it.second));
    }
  }

  return data_list;
}

syncer::SyncError AutofillWalletMetadataSyncableService::ProcessSyncChanges(
    const base::Location& from_here,
    const syncer::SyncChangeList& changes_from_sync) {
  DCHECK(thread_checker_.CalledOnValidThread());

  ApplyChangesToCache(changes_from_sync, &cache_);

  // If we're not tracking wallet data, we can't rely on the local wallet
  // data being up-to-date, so we should not do any merging with local data.
  if (!track_wallet_data_) {
    return syncer::SyncError();
  }

  std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
  std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
  GetLocalData(&profiles, &cards);

  // base::Unretained is used because the callbacks are invoked synchronously.
  base::Callback<bool(const AutofillProfile&)> address_updater =
      base::Bind(&AutofillWalletMetadataSyncableService::UpdateAddressStats,
                 base::Unretained(this));
  base::Callback<bool(const CreditCard&)> card_updater =
      base::Bind(&AutofillWalletMetadataSyncableService::UpdateCardStats,
                 base::Unretained(this));

  bool is_any_local_modified = false;

  syncer::SyncChangeList changes_to_sync;
  for (const syncer::SyncChange& change : changes_from_sync) {
    const sync_pb::WalletMetadataSpecifics& remote_metadata =
        change.sync_data().GetSpecifics().wallet_metadata();
    switch (change.change_type()) {
      case syncer::SyncChange::ACTION_ADD:
      // Intentional fall through.
      case syncer::SyncChange::ACTION_UPDATE:
        switch (remote_metadata.type()) {
          case sync_pb::WalletMetadataSpecifics::ADDRESS:
            MergeRemote(change.sync_data(), address_updater,
                        &is_any_local_modified, &profiles, &changes_to_sync);
            break;

          case sync_pb::WalletMetadataSpecifics::CARD:
            MergeRemote(change.sync_data(), card_updater,
                        &is_any_local_modified, &cards, &changes_to_sync);
            break;

          case sync_pb::WalletMetadataSpecifics::UNKNOWN:
            NOTREACHED();
            break;
        }
        break;

      // Metadata should only be deleted when the underlying data is deleted.
      case syncer::SyncChange::ACTION_DELETE:
        switch (remote_metadata.type()) {
          case sync_pb::WalletMetadataSpecifics::ADDRESS:
            UndeleteMetadataIfExisting(
                remote_metadata.id(), sync_pb::WalletMetadataSpecifics::ADDRESS,
                &profiles, &changes_to_sync);
            break;

          case sync_pb::WalletMetadataSpecifics::CARD:
            UndeleteMetadataIfExisting(remote_metadata.id(),
                                       sync_pb::WalletMetadataSpecifics::CARD,
                                       &cards, &changes_to_sync);
            break;

          case sync_pb::WalletMetadataSpecifics::UNKNOWN:
            NOTREACHED();
            break;
        }
        break;

      case syncer::SyncChange::ACTION_INVALID:
        NOTREACHED();
        break;
    }
  }

  syncer::SyncError status;
  if (!changes_to_sync.empty())
    status = SendChangesToSyncServer(changes_to_sync);
  if (is_any_local_modified) {
    // TODO(crbug.com/900607): Remove the need to listen to
    // AutofillMultipleChanged() in the new USS implementation so that we can
    // get rid of this hack.
    DCHECK(!ignore_multiple_changed_notification_);
    ignore_multiple_changed_notification_ = true;
    // TODO(crbug.com/915229): Remove once the investigation is over.
    DLOG(WARNING) << this << " ProcessSyncChanges notify the PDM";
    web_data_backend_->NotifyOfMultipleAutofillChanges();
    ignore_multiple_changed_notification_ = false;
  }

  return status;
}

void AutofillWalletMetadataSyncableService::AutofillProfileChanged(
    const AutofillProfileChange& change) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!track_wallet_data_) {
    return;
  }

  if (sync_processor_ && change.data_model() &&
      change.data_model()->record_type() != AutofillProfile::LOCAL_PROFILE) {
    std::string server_id = GetServerId(*change.data_model());
    auto it = FindServerIdAndTypeInCache(
        server_id, sync_pb::WalletMetadataSpecifics::ADDRESS, &cache_);
    if (it == cache_.end())
      return;
    // Implicitly, we filter out ADD (not in cache) and REMOVE (!data_model()).
    DCHECK(change.type() == AutofillProfileChange::UPDATE);

    const sync_pb::WalletMetadataSpecifics& remote =
        it->GetSpecifics().wallet_metadata();
    const AutofillProfile& local = *change.data_model();

    // TODO(crbug.com/915229): Remove once the investigation is over.
    DLOG(WARNING) << this << " AutofillProfileChanged " << local;

    if (!AreLocalUseStatsUpdated(remote, local) &&
        !IsLocalHasConvertedStatusUpdated(remote, local)) {
      // TODO(crbug.com/915229): Remove once the investigation is over.
      DLOG(WARNING) << this << " Nothing has changed, not syncing up.";
      return;
    }

    SendChangesToSyncServer(syncer::SyncChangeList(
        1, syncer::SyncChange(
               FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
               BuildSyncData(sync_pb::WalletMetadataSpecifics::ADDRESS,
                             server_id, local))));
  }
}

void AutofillWalletMetadataSyncableService::CreditCardChanged(
    const CreditCardChange& change) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!track_wallet_data_) {
    return;
  }

  if (sync_processor_ && change.data_model() &&
      change.data_model()->record_type() != CreditCard::LOCAL_CARD) {
    std::string server_id = GetServerId(*change.data_model());
    auto it = FindServerIdAndTypeInCache(
        server_id, sync_pb::WalletMetadataSpecifics::CARD, &cache_);
    if (it == cache_.end())
      return;
    // Implicitly, we filter out ADD (not in cache) and REMOVE (!data_model()).
    DCHECK(change.type() == AutofillProfileChange::UPDATE);

    const sync_pb::WalletMetadataSpecifics& remote =
        it->GetSpecifics().wallet_metadata();
    const CreditCard& local = *change.data_model();
    if (!AreLocalUseStatsUpdated(remote, local) &&
        !IsLocalBillingAddressUpdated(remote, local)) {
      return;
    }

    SendChangesToSyncServer(syncer::SyncChangeList(
        1,
        syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_UPDATE,
                           BuildSyncData(sync_pb::WalletMetadataSpecifics::CARD,
                                         server_id, local))));
  }
}

void AutofillWalletMetadataSyncableService::AutofillMultipleChanged() {
  if (ignore_multiple_changed_notification_) {
    // TODO(crbug.com/900607): Remove the need to listen to
    // AutofillMultipleChanged() in the new USS implementation so that we can
    // get rid of this hack.
    return;
  }

  if (sync_processor_ && track_wallet_data_)
    MergeData(cache_);
}

// static
void AutofillWalletMetadataSyncableService::CreateForWebDataServiceAndBackend(
    AutofillWebDataService* web_data_service,
    AutofillWebDataBackend* web_data_backend,
    const std::string& app_locale) {
  web_data_service->GetDBUserData()->SetUserData(
      AutofillWalletMetadataSyncableServiceUserDataKey(),
      base::WrapUnique(new AutofillWalletMetadataSyncableService(
          web_data_backend, app_locale)));
}

// static
AutofillWalletMetadataSyncableService*
AutofillWalletMetadataSyncableService::FromWebDataService(
    AutofillWebDataService* web_data_service) {
  return static_cast<AutofillWalletMetadataSyncableService*>(
      web_data_service->GetDBUserData()->GetUserData(
          AutofillWalletMetadataSyncableServiceUserDataKey()));
}

AutofillWalletMetadataSyncableService::AutofillWalletMetadataSyncableService(
    AutofillWebDataBackend* web_data_backend,
    const std::string& app_locale)
    : web_data_backend_(web_data_backend),
      scoped_observer_(this),
      track_wallet_data_(false),
      ignore_multiple_changed_notification_(false),
      weak_ptr_factory_(this) {
  scoped_observer_.Add(web_data_backend_);
}

bool AutofillWalletMetadataSyncableService::GetLocalData(
    std::unordered_map<std::string, std::unique_ptr<AutofillProfile>>* profiles,
    std::unordered_map<std::string, std::unique_ptr<CreditCard>>* cards) const {
  std::vector<std::unique_ptr<AutofillProfile>> profile_list;
  bool success =
      AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
          ->GetServerProfiles(&profile_list);
  while (!profile_list.empty()) {
    auto server_id = GetServerId(*profile_list.front());
    (*profiles)[server_id] = std::move(profile_list.front());
    profile_list.erase(profile_list.begin());
  }

  std::vector<std::unique_ptr<CreditCard>> card_list;
  success &= AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
                 ->GetServerCreditCards(&card_list);
  while (!card_list.empty()) {
    auto server_id = GetServerId(*card_list.front());
    (*cards)[server_id] = std::move(card_list.front());
    card_list.erase(card_list.begin());
  }

  return success;
}

bool AutofillWalletMetadataSyncableService::UpdateAddressStats(
    const AutofillProfile& profile) {
  // TODO(crbug.com/915229): Remove once the investigation is over.
  DLOG(WARNING) << this << " Applying change from sync " << profile;
  return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
      ->UpdateServerAddressMetadata(profile);
}

bool AutofillWalletMetadataSyncableService::UpdateCardStats(
    const CreditCard& credit_card) {
  return AutofillTable::FromWebDatabase(web_data_backend_->GetDatabase())
      ->UpdateServerCardMetadata(credit_card);
}

syncer::SyncError
AutofillWalletMetadataSyncableService::SendChangesToSyncServer(
    const syncer::SyncChangeList& changes_to_sync) {
  DCHECK(sync_processor_);
  ApplyChangesToCache(changes_to_sync, &cache_);
  return sync_processor_->ProcessSyncChanges(FROM_HERE, changes_to_sync);
}

syncer::SyncMergeResult AutofillWalletMetadataSyncableService::MergeData(
    const syncer::SyncDataList& sync_data) {
  // If we're not tracking wallet data, we can't rely on the local wallet
  // data being up-to-date, so we should not do any merging with local data.
  DCHECK(track_wallet_data_);

  std::unordered_map<std::string, std::unique_ptr<AutofillProfile>> profiles;
  std::unordered_map<std::string, std::unique_ptr<CreditCard>> cards;
  GetLocalData(&profiles, &cards);

  syncer::SyncMergeResult result(syncer::AUTOFILL_WALLET_METADATA);
  result.set_num_items_before_association(profiles.size() + cards.size());

  // base::Unretained is used because the callbacks are invoked synchronously.
  base::Callback<bool(const AutofillProfile&)> address_updater =
      base::Bind(&AutofillWalletMetadataSyncableService::UpdateAddressStats,
                 base::Unretained(this));
  base::Callback<bool(const CreditCard&)> card_updater =
      base::Bind(&AutofillWalletMetadataSyncableService::UpdateCardStats,
                 base::Unretained(this));

  bool is_any_local_modified = false;

  syncer::SyncChangeList changes_to_sync;
  for (const syncer::SyncData& remote : sync_data) {
    DCHECK(remote.IsValid());
    DCHECK_EQ(syncer::AUTOFILL_WALLET_METADATA, remote.GetDataType());
    switch (remote.GetSpecifics().wallet_metadata().type()) {
      case sync_pb::WalletMetadataSpecifics::ADDRESS:
        if (!MergeRemote(remote, address_updater, &is_any_local_modified,
                         &profiles, &changes_to_sync)) {
          changes_to_sync.push_back(syncer::SyncChange(
              FROM_HERE, syncer::SyncChange::ACTION_DELETE, remote));
        }
        break;

      case sync_pb::WalletMetadataSpecifics::CARD:
        if (!MergeRemote(remote, card_updater, &is_any_local_modified, &cards,
                         &changes_to_sync)) {
          changes_to_sync.push_back(syncer::SyncChange(
              FROM_HERE, syncer::SyncChange::ACTION_DELETE, remote));
        }
        break;

      case sync_pb::WalletMetadataSpecifics::UNKNOWN:
        NOTREACHED();
        break;
    }
  }

  // The remainder of |profiles| were not listed in |sync_data|.
  for (const auto& it : profiles) {
    changes_to_sync.push_back(syncer::SyncChange(
        FROM_HERE, syncer::SyncChange::ACTION_ADD,
        BuildSyncData(sync_pb::WalletMetadataSpecifics::ADDRESS, it.first,
                      *it.second)));
  }

  // The remainder of |cards| were not listed in |sync_data|.
  for (const auto& it : cards) {
    changes_to_sync.push_back(
        syncer::SyncChange(FROM_HERE, syncer::SyncChange::ACTION_ADD,
                           BuildSyncData(sync_pb::WalletMetadataSpecifics::CARD,
                                         it.first, *it.second)));
  }

  // The only operation that is performed locally in response to a sync is an
  // update. Adds and deletes are performed in response to changes to the Wallet
  // data.
  result.set_num_items_after_association(result.num_items_before_association());
  result.set_num_items_added(0);
  result.set_num_items_deleted(0);

  if (!changes_to_sync.empty())
    result.set_error(SendChangesToSyncServer(changes_to_sync));
  if (is_any_local_modified) {
    // TODO(crbug.com/900607): Remove the need to listen to
    // AutofillMultipleChanged() in the new USS implementation so that we can
    // get rid of this hack.
    DCHECK(!ignore_multiple_changed_notification_);
    ignore_multiple_changed_notification_ = true;
    // TODO(crbug.com/915229): Remove once the investigation is over.
    DLOG(WARNING) << this << " MergeData notify the PDM";
    web_data_backend_->NotifyOfMultipleAutofillChanges();
    ignore_multiple_changed_notification_ = false;
  }

  return result;
}

}  // namespace autofill
