// Copyright 2013 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/sync/engine_impl/commit_util.h"

#include <limits>
#include <string>
#include <vector>

#include "base/debug/dump_without_crashing.h"
#include "base/strings/string_util.h"
#include "components/sync/base/attachment_id_proto.h"
#include "components/sync/base/time.h"
#include "components/sync/base/unique_position.h"
#include "components/sync/engine_impl/syncer_proto_util.h"
#include "components/sync/protocol/bookmark_specifics.pb.h"
#include "components/sync/syncable/directory.h"
#include "components/sync/syncable/entry.h"
#include "components/sync/syncable/model_neutral_mutable_entry.h"
#include "components/sync/syncable/syncable_base_transaction.h"
#include "components/sync/syncable/syncable_base_write_transaction.h"
#include "components/sync/syncable/syncable_changes_version.h"
#include "components/sync/syncable/syncable_proto_util.h"
#include "components/sync/syncable/syncable_util.h"

using std::set;
using std::string;
using std::vector;

namespace syncer {

using syncable::Entry;
using syncable::Id;

namespace commit_util {

void AddExtensionsActivityToMessage(
    ExtensionsActivity* activity,
    ExtensionsActivity::Records* extensions_activity_buffer,
    sync_pb::CommitMessage* message) {
  // This isn't perfect, since the set of extensions activity may not correlate
  // exactly with the items being committed.  That's OK as long as we're looking
  // for a rough estimate of extensions activity, not an precise mapping of
  // which commits were triggered by which extension.
  //
  // We will push this list of extensions activity back into the
  // ExtensionsActivityMonitor if this commit fails.  That's why we must keep a
  // copy of these records in the cycle.
  activity->GetAndClearRecords(extensions_activity_buffer);

  const ExtensionsActivity::Records& records = *extensions_activity_buffer;
  for (ExtensionsActivity::Records::const_iterator it = records.begin();
       it != records.end(); ++it) {
    sync_pb::ChromiumExtensionsActivity* activity_message =
        message->add_extensions_activity();
    activity_message->set_extension_id(it->second.extension_id);
    activity_message->set_bookmark_writes_since_last_commit(
        it->second.bookmark_write_count);
  }
}

void AddClientConfigParamsToMessage(ModelTypeSet enabled_types,
                                    bool cookie_jar_mismatch,
                                    sync_pb::CommitMessage* message) {
  sync_pb::ClientConfigParams* config_params = message->mutable_config_params();
  for (ModelTypeSet::Iterator it = enabled_types.First(); it.Good(); it.Inc()) {
    if (ProxyTypes().Has(it.Get()))
      continue;
    int field_number = GetSpecificsFieldNumberFromModelType(it.Get());
    config_params->mutable_enabled_type_ids()->Add(field_number);
  }
  config_params->set_tabs_datatype_enabled(enabled_types.Has(PROXY_TABS));
  config_params->set_cookie_jar_mismatch(cookie_jar_mismatch);
}

namespace {

void SetEntrySpecifics(const Entry& meta_entry,
                       sync_pb::SyncEntity* sync_entry) {
  // Add the new style extension and the folder bit.
  sync_entry->mutable_specifics()->CopyFrom(meta_entry.GetSpecifics());
  sync_entry->set_folder(meta_entry.GetIsDir());

  CHECK(!sync_entry->specifics().password().has_client_only_encrypted_data());
  DCHECK_EQ(meta_entry.GetModelType(), GetModelType(*sync_entry));
}

void SetAttachmentIds(const Entry& meta_entry,
                      sync_pb::SyncEntity* sync_entry) {
  const sync_pb::AttachmentMetadata& attachment_metadata =
      meta_entry.GetAttachmentMetadata();
  for (int i = 0; i < attachment_metadata.record_size(); ++i) {
    *sync_entry->add_attachment_id() = attachment_metadata.record(i).id();
  }
}

}  // namespace

void BuildCommitItem(const syncable::Entry& meta_entry,
                     sync_pb::SyncEntity* sync_entry) {
  syncable::Id id = meta_entry.GetId();
  sync_entry->set_id_string(SyncableIdToProto(id));

  string name = meta_entry.GetNonUniqueName();
  CHECK(!name.empty());  // Make sure this isn't an update.
  // Note: Truncation is also performed in WriteNode::SetTitle(..). But this
  // call is still necessary to handle any title changes that might originate
  // elsewhere, or already be persisted in the directory.
  base::TruncateUTF8ToByteSize(name, 255, &name);
  sync_entry->set_name(name);

  // Set the non_unique_name.  If we do, the server ignores
  // the |name| value (using |non_unique_name| instead), and will return
  // in the CommitResponse a unique name if one is generated.
  // We send both because it may aid in logging.
  sync_entry->set_non_unique_name(name);

  if (!meta_entry.GetUniqueClientTag().empty()) {
    sync_entry->set_client_defined_unique_tag(meta_entry.GetUniqueClientTag());
  }

  // Deleted items with server-unknown parent ids can be a problem so we set
  // the parent to 0. (TODO(sync): Still true in protocol?).
  Id new_parent_id;
  if (meta_entry.GetIsDel() && !meta_entry.GetParentId().ServerKnows()) {
    new_parent_id = syncable::BaseTransaction::root_id();
  } else {
    new_parent_id = meta_entry.GetParentId();
  }

  if (meta_entry.ShouldMaintainHierarchy()) {
    sync_entry->set_parent_id_string(SyncableIdToProto(new_parent_id));
  }

  // If our parent has changed, send up the old one so the server
  // can correctly deal with multiple parents.
  // TODO(nick): With the server keeping track of the primary sync parent,
  // it should not be necessary to provide the old_parent_id: the version
  // number should suffice.
  Id server_parent_id = meta_entry.GetServerParentId();
  if (new_parent_id != server_parent_id && !server_parent_id.IsNull() &&
      0 != meta_entry.GetBaseVersion() &&
      syncable::CHANGES_VERSION != meta_entry.GetBaseVersion()) {
    sync_entry->set_old_parent_id(SyncableIdToProto(server_parent_id));
  }

  int64_t version = meta_entry.GetBaseVersion();
  if (syncable::CHANGES_VERSION == version || 0 == version) {
    // Undeletions are only supported for items that have a client tag.
    DCHECK(!id.ServerKnows() || !meta_entry.GetUniqueClientTag().empty())
        << meta_entry;

    // Version 0 means to create or undelete an object.
    sync_entry->set_version(0);
  } else {
    DCHECK(id.ServerKnows()) << meta_entry;
    sync_entry->set_version(meta_entry.GetBaseVersion());
  }
  sync_entry->set_ctime(TimeToProtoTime(meta_entry.GetCtime()));
  sync_entry->set_mtime(TimeToProtoTime(meta_entry.GetMtime()));

  SetAttachmentIds(meta_entry, sync_entry);

  // Handle bookmarks separately.
  if (meta_entry.GetSpecifics().has_bookmark()) {
    if (meta_entry.GetIsDel()) {
      sync_entry->set_deleted(true);
    } else {
      // Both insert_after_item_id and position_in_parent fields are set only
      // for legacy reasons.  See comments in sync.proto for more information.
      const Id& prev_id = meta_entry.GetPredecessorId();
      string prev_id_string =
          prev_id.IsNull() ? string() : prev_id.GetServerId();
      sync_entry->set_insert_after_item_id(prev_id_string);
      sync_entry->set_position_in_parent(
          meta_entry.GetUniquePosition().ToInt64());
      meta_entry.GetUniquePosition().ToProto(
          sync_entry->mutable_unique_position());
      if (!meta_entry.GetUniquePosition().IsValid()) {
        // Should never upload invalid unique position for bookmark to server.
        base::debug::DumpWithoutCrashing();
      }
    }
    // Always send specifics for bookmarks.
    SetEntrySpecifics(meta_entry, sync_entry);
    return;
  }

  // Deletion is final on the server, let's move things and then delete them.
  if (meta_entry.GetIsDel()) {
    sync_entry->set_deleted(true);

    sync_pb::EntitySpecifics type_only_specifics;
    AddDefaultFieldValue(meta_entry.GetModelType(),
                         sync_entry->mutable_specifics());
  } else {
    SetEntrySpecifics(meta_entry, sync_entry);
  }
}

// Helpers for ProcessSingleCommitResponse.
namespace {

void LogServerError(const sync_pb::CommitResponse_EntryResponse& res) {
  if (res.has_error_message())
    LOG(WARNING) << "  " << res.error_message();
  else
    LOG(WARNING) << "  No detailed error message returned from server";
}

const string& GetResultingPostCommitName(
    const sync_pb::SyncEntity& committed_entry,
    const sync_pb::CommitResponse_EntryResponse& entry_response) {
  const string& response_name =
      SyncerProtoUtil::NameFromCommitEntryResponse(entry_response);
  if (!response_name.empty())
    return response_name;
  return SyncerProtoUtil::NameFromSyncEntity(committed_entry);
}

bool UpdateVersionAfterCommit(
    const sync_pb::SyncEntity& committed_entry,
    const sync_pb::CommitResponse_EntryResponse& entry_response,
    const syncable::Id& pre_commit_id,
    syncable::ModelNeutralMutableEntry* local_entry) {
  int64_t old_version = local_entry->GetBaseVersion();
  int64_t new_version = entry_response.version();
  bool bad_commit_version = false;
  if (committed_entry.deleted() && !local_entry->GetUniqueClientTag().empty()) {
    // If the item was deleted, and it's undeletable (uses the client tag),
    // change the version back to zero.  We must set the version to zero so
    // that the server knows to re-create the item if it gets committed
    // later for undeletion.
    new_version = 0;
  } else if (!pre_commit_id.ServerKnows()) {
    bad_commit_version = 0 == new_version;
  } else {
    bad_commit_version = old_version > new_version;
  }
  if (bad_commit_version) {
    LOG(ERROR) << "Bad version in commit return for " << *local_entry
               << " new_id:" << SyncableIdFromProto(entry_response.id_string())
               << " new_version:" << entry_response.version();
    return false;
  }

  // Update the base version and server version.  The base version must change
  // here, even if syncing_was_set is false; that's because local changes were
  // on top of the successfully committed version.
  local_entry->PutBaseVersion(new_version);
  DVLOG(1) << "Commit is changing base version of " << local_entry->GetId()
           << " to: " << new_version;
  local_entry->PutServerVersion(new_version);
  return true;
}

bool ChangeIdAfterCommit(
    const sync_pb::CommitResponse_EntryResponse& entry_response,
    const syncable::Id& pre_commit_id,
    syncable::ModelNeutralMutableEntry* local_entry) {
  syncable::BaseWriteTransaction* trans = local_entry->base_write_transaction();
  const syncable::Id& entry_response_id =
      SyncableIdFromProto(entry_response.id_string());
  if (entry_response_id != pre_commit_id) {
    if (pre_commit_id.ServerKnows()) {
      // The server can sometimes generate a new ID on commit; for example,
      // when committing an undeletion.
      DVLOG(1) << " ID changed while committing an old entry. " << pre_commit_id
               << " became " << entry_response_id << ".";
    }
    syncable::ModelNeutralMutableEntry same_id(trans, syncable::GET_BY_ID,
                                               entry_response_id);
    // We should trap this before this function.
    if (same_id.good()) {
      LOG(ERROR) << "ID clash with id " << entry_response_id
                 << " during commit " << same_id;
      return false;
    }
    ChangeEntryIDAndUpdateChildren(trans, local_entry, entry_response_id);
    DVLOG(1) << "Changing ID to " << entry_response_id;
  }
  return true;
}

void UpdateServerFieldsAfterCommit(
    const sync_pb::SyncEntity& committed_entry,
    const sync_pb::CommitResponse_EntryResponse& entry_response,
    syncable::ModelNeutralMutableEntry* local_entry) {
  // We just committed an entry successfully, and now we want to make our view
  // of the server state consistent with the server state. We must be careful;
  // |entry_response| and |committed_entry| have some identically named
  // fields.  We only want to consider fields from |committed_entry| when there
  // is not an overriding field in the |entry_response|.  We do not want to
  // update the server data from the local data in the entry -- it's possible
  // that the local data changed during the commit, and even if not, the server
  // has the last word on the values of several properties.

  local_entry->PutServerIsDel(committed_entry.deleted());
  if (committed_entry.deleted()) {
    // Don't clobber any other fields of deleted objects.
    return;
  }

  local_entry->PutServerIsDir(
      (committed_entry.folder() ||
       committed_entry.bookmarkdata().bookmark_folder()));
  local_entry->PutServerSpecifics(committed_entry.specifics());
  local_entry->PutServerAttachmentMetadata(
      CreateAttachmentMetadata(committed_entry.attachment_id()));
  local_entry->PutServerMtime(ProtoTimeToTime(committed_entry.mtime()));
  local_entry->PutServerCtime(ProtoTimeToTime(committed_entry.ctime()));
  if (committed_entry.has_unique_position()) {
    local_entry->PutServerUniquePosition(
        UniquePosition::FromProto(committed_entry.unique_position()));
  }

  // TODO(nick): The server doesn't set entry_response.server_parent_id in
  // practice; to update SERVER_PARENT_ID appropriately here we'd need to
  // get the post-commit ID of the parent indicated by
  // committed_entry.parent_id_string(). That should be inferrable from the
  // information we have, but it's a bit convoluted to pull it out directly.
  // Getting this right is important: SERVER_PARENT_ID gets fed back into
  // old_parent_id during the next commit.
  local_entry->PutServerParentId(local_entry->GetParentId());
  local_entry->PutServerNonUniqueName(
      GetResultingPostCommitName(committed_entry, entry_response));

  if (local_entry->GetIsUnappliedUpdate()) {
    // This shouldn't happen; an unapplied update shouldn't be committed, and
    // if it were, the commit should have failed.  But if it does happen: we've
    // just overwritten the update info, so clear the flag.
    local_entry->PutIsUnappliedUpdate(false);
  }
}

void ProcessSuccessfulCommitResponse(
    const sync_pb::SyncEntity& committed_entry,
    const sync_pb::CommitResponse_EntryResponse& entry_response,
    const syncable::Id& pre_commit_id,
    syncable::ModelNeutralMutableEntry* local_entry,
    bool dirty_sync_was_set,
    set<syncable::Id>* deleted_folders) {
  DCHECK(local_entry->GetIsUnsynced());

  // Update SERVER_VERSION and BASE_VERSION.
  if (!UpdateVersionAfterCommit(committed_entry, entry_response, pre_commit_id,
                                local_entry)) {
    LOG(ERROR) << "Bad version in commit return for " << *local_entry
               << " new_id:" << SyncableIdFromProto(entry_response.id_string())
               << " new_version:" << entry_response.version();
    return;
  }

  // If the server gave us a new ID, apply it.
  if (!ChangeIdAfterCommit(entry_response, pre_commit_id, local_entry)) {
    return;
  }

  // Update our stored copy of the server state.
  UpdateServerFieldsAfterCommit(committed_entry, entry_response, local_entry);

  // If the item doesn't need to be committed again (an item might need to be
  // committed again if it changed locally during the commit), we can remove
  // it from the unsynced list.
  if (!dirty_sync_was_set) {
    local_entry->PutIsUnsynced(false);
  }

  // Make a note of any deleted folders, whose children would have
  // been recursively deleted.
  // TODO(nick): Here, commit_message.deleted() would be more correct than
  // local_entry->GetIsDel().  For example, an item could be renamed, and then
  // deleted during the commit of the rename.  Unit test & fix.
  if (local_entry->GetIsDir() && local_entry->GetIsDel()) {
    deleted_folders->insert(local_entry->GetId());
  }
}

}  // namespace

sync_pb::CommitResponse::ResponseType ProcessSingleCommitResponse(
    syncable::BaseWriteTransaction* trans,
    const sync_pb::CommitResponse_EntryResponse& server_entry,
    const sync_pb::SyncEntity& commit_request_entry,
    int64_t metahandle,
    set<syncable::Id>* deleted_folders) {
  syncable::ModelNeutralMutableEntry local_entry(trans, syncable::GET_BY_HANDLE,
                                                 metahandle);
  CHECK(local_entry.good());
  bool dirty_sync_was_set = local_entry.GetDirtySync();
  local_entry.PutDirtySync(false);
  local_entry.PutSyncing(false);

  sync_pb::CommitResponse::ResponseType response = server_entry.response_type();
  if (!sync_pb::CommitResponse::ResponseType_IsValid(response)) {
    LOG(ERROR) << "Commit response has unknown response type! Possibly out "
                  "of date client?";
    return sync_pb::CommitResponse::INVALID_MESSAGE;
  }
  if (sync_pb::CommitResponse::TRANSIENT_ERROR == response) {
    DVLOG(1) << "Transient Error Committing: " << local_entry;
    LogServerError(server_entry);
    return sync_pb::CommitResponse::TRANSIENT_ERROR;
  }
  if (sync_pb::CommitResponse::INVALID_MESSAGE == response) {
    LOG(ERROR) << "Error Commiting: " << local_entry;
    LogServerError(server_entry);
    return response;
  }
  if (sync_pb::CommitResponse::CONFLICT == response) {
    DVLOG(1) << "Conflict Committing: " << local_entry;
    return response;
  }
  if (sync_pb::CommitResponse::RETRY == response) {
    DVLOG(1) << "Retry Committing: " << local_entry;
    return response;
  }
  if (sync_pb::CommitResponse::OVER_QUOTA == response) {
    LOG(WARNING) << "Hit deprecated OVER_QUOTA Committing: " << local_entry;
    return response;
  }
  if (!server_entry.has_id_string()) {
    LOG(ERROR) << "Commit response has no id";
    return sync_pb::CommitResponse::INVALID_MESSAGE;
  }

  // Implied by the IsValid call above, but here for clarity.
  DCHECK_EQ(sync_pb::CommitResponse::SUCCESS, response) << response;
  // Check to see if we've been given the ID of an existing entry. If so treat
  // it as an error response and retry later.
  const syncable::Id& server_entry_id =
      SyncableIdFromProto(server_entry.id_string());
  if (local_entry.GetId() != server_entry_id) {
    Entry e(trans, syncable::GET_BY_ID, server_entry_id);
    if (e.good()) {
      LOG(ERROR) << "Got duplicate id when commiting id: "
                 << local_entry.GetId() << ". Treating as an error return";
      return sync_pb::CommitResponse::INVALID_MESSAGE;
    }
  }

  if (server_entry.version() == 0) {
    LOG(WARNING) << "Server returned a zero version on a commit response.";
  }

  ProcessSuccessfulCommitResponse(commit_request_entry, server_entry,
                                  local_entry.GetId(), &local_entry,
                                  dirty_sync_was_set, deleted_folders);
  return response;
}

}  // namespace commit_util

}  // namespace syncer
