// Copyright 2012 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 "sync/engine/conflict_resolver.h"

#include <list>
#include <set>
#include <string>

#include "base/metrics/histogram.h"
#include "sync/engine/conflict_util.h"
#include "sync/engine/syncer_util.h"
#include "sync/internal_api/public/sessions/update_counters.h"
#include "sync/sessions/status_controller.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/mutable_entry.h"
#include "sync/syncable/syncable_write_transaction.h"
#include "sync/util/cryptographer.h"

using std::list;
using std::set;

namespace syncer {

using sessions::StatusController;
using syncable::Directory;
using syncable::Entry;
using syncable::Id;
using syncable::MutableEntry;
using syncable::WriteTransaction;

namespace {

// Returns true iff the set of attachment ids contained in attachment_metadata
// matches the set of ids contained in server_attachment_metadata.
bool AttachmentMetadataMatches(const MutableEntry& entity) {
  const sync_pb::AttachmentMetadata& local = entity.GetAttachmentMetadata();
  const sync_pb::AttachmentMetadata& server =
      entity.GetServerAttachmentMetadata();
  if (local.record_size() != server.record_size()) {
    return false;
  }

  // The order of records in local and server may be different so use a std::set
  // to determine if they are equivalent.
  std::set<std::string> local_ids;
  for (int i = 0; i < local.record_size(); ++i) {
    const sync_pb::AttachmentMetadataRecord& record = local.record(i);
    DCHECK(record.is_on_server());
    local_ids.insert(record.id().SerializeAsString());
  }
  for (int i = 0; i < server.record_size(); ++i) {
    const sync_pb::AttachmentMetadataRecord& record = server.record(i);
    DCHECK(record.is_on_server());
    if (local_ids.find(record.id().SerializeAsString()) == local_ids.end()) {
      return false;
    }
  }

  return true;
}

}  // namespace

ConflictResolver::ConflictResolver() {
}

ConflictResolver::~ConflictResolver() {
}

void ConflictResolver::ProcessSimpleConflict(WriteTransaction* trans,
                                             const Id& id,
                                             const Cryptographer* cryptographer,
                                             StatusController* status,
                                             UpdateCounters* counters) {
  MutableEntry entry(trans, syncable::GET_BY_ID, id);
  // Must be good as the entry won't have been cleaned up.
  CHECK(entry.good());

  // This function can only resolve simple conflicts.  Simple conflicts have
  // both IS_UNSYNCED and IS_UNAPPLIED_UDPATE set.
  if (!entry.GetIsUnappliedUpdate() || !entry.GetIsUnsynced()) {
    // This is very unusual, but it can happen in tests.  We may be able to
    // assert NOTREACHED() here when those tests are updated.
    return;
  }

  if (entry.GetIsDel() && entry.GetServerIsDel()) {
    // we've both deleted it, so lets just drop the need to commit/update this
    // entry.
    entry.PutIsUnsynced(false);
    entry.PutIsUnappliedUpdate(false);
    // we've made changes, but they won't help syncing progress.
    // METRIC simple conflict resolved by merge.
    return;
  }

  // This logic determines "client wins" vs. "server wins" strategy picking.
  // By the time we get to this point, we rely on the following to be true:
  // a) We can decrypt both the local and server data (else we'd be in
  //    conflict encryption and not attempting to resolve).
  // b) All unsynced changes have been re-encrypted with the default key (
  //    occurs either in AttemptToUpdateEntry, SetEncryptionPassphrase,
  //    SetDecryptionPassphrase, or RefreshEncryption).
  // c) Base_server_specifics having a valid datatype means that we received
  //    an undecryptable update that only changed specifics, and since then have
  //    not received any further non-specifics-only or decryptable updates.
  // d) If the server_specifics match specifics, server_specifics are
  //    encrypted with the default key, and all other visible properties match,
  //    then we can safely ignore the local changes as redundant.
  // e) Otherwise if the base_server_specifics match the server_specifics, no
  //    functional change must have been made server-side (else
  //    base_server_specifics would have been cleared), and we can therefore
  //    safely ignore the server changes as redundant.
  // f) Otherwise, it's in general safer to ignore local changes, with the
  //    exception of deletion conflicts (choose to undelete) and conflicts
  //    where the non_unique_name or parent don't match.
  if (!entry.GetServerIsDel()) {
    // TODO(nick): The current logic is arbitrary; instead, it ought to be made
    // consistent with the ModelAssociator behavior for a datatype.  It would
    // be nice if we could route this back to ModelAssociator code to pick one
    // of three options: CLIENT, SERVER, or MERGE.  Some datatypes (autofill)
    // are easily mergeable.
    // See http://crbug.com/77339.
    bool name_matches = entry.GetNonUniqueName() ==
        entry.GetServerNonUniqueName();
    bool parent_matches = entry.GetParentId() == entry.GetServerParentId();
    bool entry_deleted = entry.GetIsDel();
    // The position check might fail spuriously if one of the positions was
    // based on a legacy random suffix, rather than a deterministic one based on
    // originator_cache_guid and originator_item_id.  If an item is being
    // modified regularly, it shouldn't take long for the suffix and position to
    // be updated, so such false failures shouldn't be a problem for long.
    //
    // Lucky for us, it's OK to be wrong here.  The position_matches check is
    // allowed to return false negatives, as long as it returns no false
    // positives.
    bool position_matches = parent_matches &&
         entry.GetServerUniquePosition().Equals(entry.GetUniquePosition());
    const sync_pb::EntitySpecifics& specifics = entry.GetSpecifics();
    const sync_pb::EntitySpecifics& server_specifics =
        entry.GetServerSpecifics();
    const sync_pb::EntitySpecifics& base_server_specifics =
        entry.GetBaseServerSpecifics();
    std::string decrypted_specifics, decrypted_server_specifics;
    bool specifics_match = false;
    bool server_encrypted_with_default_key = false;
    if (specifics.has_encrypted()) {
      DCHECK(cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted()));
      decrypted_specifics = cryptographer->DecryptToString(
          specifics.encrypted());
    } else {
      decrypted_specifics = specifics.SerializeAsString();
    }
    if (server_specifics.has_encrypted()) {
      server_encrypted_with_default_key =
          cryptographer->CanDecryptUsingDefaultKey(
              server_specifics.encrypted());
      decrypted_server_specifics = cryptographer->DecryptToString(
          server_specifics.encrypted());
    } else {
      decrypted_server_specifics = server_specifics.SerializeAsString();
    }
    if (decrypted_server_specifics == decrypted_specifics &&
        server_encrypted_with_default_key == specifics.has_encrypted()) {
      specifics_match = true;
    }
    bool base_server_specifics_match = false;
    if (server_specifics.has_encrypted() &&
        IsRealDataType(GetModelTypeFromSpecifics(base_server_specifics))) {
      std::string decrypted_base_server_specifics;
      if (!base_server_specifics.has_encrypted()) {
        decrypted_base_server_specifics =
            base_server_specifics.SerializeAsString();
      } else {
        decrypted_base_server_specifics = cryptographer->DecryptToString(
            base_server_specifics.encrypted());
      }
      if (decrypted_server_specifics == decrypted_base_server_specifics)
          base_server_specifics_match = true;
    }

    bool attachment_metadata_matches = AttachmentMetadataMatches(entry);
    if (!entry_deleted && name_matches && parent_matches && specifics_match &&
        position_matches && attachment_metadata_matches) {
      DVLOG(1) << "Resolving simple conflict, everything matches, ignoring "
               << "changes for: " << entry;
      conflict_util::IgnoreConflict(&entry);
      UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
                                CHANGES_MATCH,
                                CONFLICT_RESOLUTION_SIZE);
    } else if (base_server_specifics_match) {
      DVLOG(1) << "Resolving simple conflict, ignoring server encryption "
               << " changes for: " << entry;
      status->increment_num_server_overwrites();
      counters->num_server_overwrites++;
      conflict_util::OverwriteServerChanges(&entry);
      UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
                                IGNORE_ENCRYPTION,
                                CONFLICT_RESOLUTION_SIZE);
    } else if (entry_deleted || !name_matches || !parent_matches) {
      // NOTE: The update application logic assumes that conflict resolution
      // will never result in changes to the local hierarchy.  The entry_deleted
      // and !parent_matches cases here are critical to maintaining that
      // assumption.
      conflict_util::OverwriteServerChanges(&entry);
      status->increment_num_server_overwrites();
      counters->num_server_overwrites++;
      DVLOG(1) << "Resolving simple conflict, overwriting server changes "
               << "for: " << entry;
      UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
                                OVERWRITE_SERVER,
                                CONFLICT_RESOLUTION_SIZE);
    } else {
      DVLOG(1) << "Resolving simple conflict, ignoring local changes for: "
               << entry;
      conflict_util::IgnoreLocalChanges(&entry);
      status->increment_num_local_overwrites();
      counters->num_local_overwrites++;
      UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
                                OVERWRITE_LOCAL,
                                CONFLICT_RESOLUTION_SIZE);
    }
    // Now that we've resolved the conflict, clear the prev server
    // specifics.
    entry.PutBaseServerSpecifics(sync_pb::EntitySpecifics());
  } else {  // SERVER_IS_DEL is true
    if (entry.GetIsDir()) {
      Directory::Metahandles children;
      trans->directory()->GetChildHandlesById(trans,
                                              entry.GetId(),
                                              &children);
      // If a server deleted folder has local contents it should be a hierarchy
      // conflict.  Hierarchy conflicts should not be processed by this
      // function.
      DCHECK(children.empty());
    }

    // The entry is deleted on the server but still exists locally.
    // We undelete it by overwriting the server's tombstone with the local
    // data.
    conflict_util::OverwriteServerChanges(&entry);
    status->increment_num_server_overwrites();
    counters->num_server_overwrites++;
    DVLOG(1) << "Resolving simple conflict, undeleting server entry: "
             << entry;
    UMA_HISTOGRAM_ENUMERATION("Sync.ResolveSimpleConflict",
                              UNDELETE,
                              CONFLICT_RESOLUTION_SIZE);
  }
}

void ConflictResolver::ResolveConflicts(
    syncable::WriteTransaction* trans,
    const Cryptographer* cryptographer,
    const std::set<syncable::Id>& simple_conflict_ids,
    sessions::StatusController* status,
    UpdateCounters* counters) {
  // Iterate over simple conflict items.
  set<Id>::const_iterator it;
  for (it = simple_conflict_ids.begin();
       it != simple_conflict_ids.end();
       ++it) {
    // We don't resolve conflicts for control types here.
    Entry conflicting_node(trans, syncable::GET_BY_ID, *it);
    CHECK(conflicting_node.good());
    if (IsControlType(
        GetModelTypeFromSpecifics(conflicting_node.GetSpecifics()))) {
      continue;
    }

    ProcessSimpleConflict(trans, *it, cryptographer, status, counters);
  }
  return;
}

}  // namespace syncer
