// Copyright (c) 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/syncer_proto_util.h"

#include <map>

#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
#include "google_apis/google_api_keys.h"
#include "sync/engine/net/server_connection_manager.h"
#include "sync/engine/syncer.h"
#include "sync/engine/syncer_types.h"
#include "sync/engine/traffic_logger.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/protocol/sync_enums.pb.h"
#include "sync/protocol/sync_protocol_error.h"
#include "sync/sessions/sync_session.h"
#include "sync/syncable/directory.h"
#include "sync/syncable/entry.h"
#include "sync/syncable/syncable-inl.h"
#include "sync/syncable/syncable_proto_util.h"
#include "sync/util/time.h"

using std::string;
using std::stringstream;
using sync_pb::ClientToServerMessage;
using sync_pb::ClientToServerResponse;

namespace syncer {

using sessions::SyncSession;
using syncable::BASE_VERSION;
using syncable::CTIME;
using syncable::ID;
using syncable::IS_DEL;
using syncable::IS_DIR;
using syncable::IS_UNSYNCED;
using syncable::MTIME;
using syncable::PARENT_ID;

namespace {

// Time to backoff syncing after receiving a throttled response.
const int kSyncDelayAfterThrottled = 2 * 60 * 60;  // 2 hours

void LogResponseProfilingData(const ClientToServerResponse& response) {
  if (response.has_profiling_data()) {
    stringstream response_trace;
    response_trace << "Server response trace:";

    if (response.profiling_data().has_user_lookup_time()) {
      response_trace << " user lookup: "
                     << response.profiling_data().user_lookup_time() << "ms";
    }

    if (response.profiling_data().has_meta_data_write_time()) {
      response_trace << " meta write: "
                     << response.profiling_data().meta_data_write_time()
                     << "ms";
    }

    if (response.profiling_data().has_meta_data_read_time()) {
      response_trace << " meta read: "
                     << response.profiling_data().meta_data_read_time() << "ms";
    }

    if (response.profiling_data().has_file_data_write_time()) {
      response_trace << " file write: "
                     << response.profiling_data().file_data_write_time()
                     << "ms";
    }

    if (response.profiling_data().has_file_data_read_time()) {
      response_trace << " file read: "
                     << response.profiling_data().file_data_read_time() << "ms";
    }

    if (response.profiling_data().has_total_request_time()) {
      response_trace << " total time: "
                     << response.profiling_data().total_request_time() << "ms";
    }
    DVLOG(1) << response_trace.str();
  }
}

SyncerError ServerConnectionErrorAsSyncerError(
    const HttpResponse::ServerConnectionCode server_status) {
  switch (server_status) {
    case HttpResponse::CONNECTION_UNAVAILABLE:
      return NETWORK_CONNECTION_UNAVAILABLE;
    case HttpResponse::IO_ERROR:
      return NETWORK_IO_ERROR;
    case HttpResponse::SYNC_SERVER_ERROR:
      // FIXME what does this mean?
      return SYNC_SERVER_ERROR;
    case HttpResponse::SYNC_AUTH_ERROR:
      return SYNC_AUTH_ERROR;
    case HttpResponse::RETRY:
      return SERVER_RETURN_TRANSIENT_ERROR;
    case HttpResponse::SERVER_CONNECTION_OK:
    case HttpResponse::NONE:
    default:
      NOTREACHED();
      return UNSET;
  }
}

SyncProtocolErrorType PBErrorTypeToSyncProtocolErrorType(
    const sync_pb::SyncEnums::ErrorType& error_type) {
  switch (error_type) {
    case sync_pb::SyncEnums::SUCCESS:
      return SYNC_SUCCESS;
    case sync_pb::SyncEnums::NOT_MY_BIRTHDAY:
      return NOT_MY_BIRTHDAY;
    case sync_pb::SyncEnums::THROTTLED:
      return THROTTLED;
    case sync_pb::SyncEnums::CLEAR_PENDING:
      return CLEAR_PENDING;
    case sync_pb::SyncEnums::TRANSIENT_ERROR:
      return TRANSIENT_ERROR;
    case sync_pb::SyncEnums::MIGRATION_DONE:
      return MIGRATION_DONE;
    case sync_pb::SyncEnums::DISABLED_BY_ADMIN:
      return DISABLED_BY_ADMIN;
    case sync_pb::SyncEnums::PARTIAL_FAILURE:
      return PARTIAL_FAILURE;
    case sync_pb::SyncEnums::CLIENT_DATA_OBSOLETE:
      return CLIENT_DATA_OBSOLETE;
    case sync_pb::SyncEnums::UNKNOWN:
      return UNKNOWN_ERROR;
    default:
      NOTREACHED();
      return UNKNOWN_ERROR;
  }
}

ClientAction PBActionToClientAction(const sync_pb::SyncEnums::Action& action) {
  switch (action) {
    case sync_pb::SyncEnums::UPGRADE_CLIENT:
      return UPGRADE_CLIENT;
    case sync_pb::SyncEnums::CLEAR_USER_DATA_AND_RESYNC:
      return CLEAR_USER_DATA_AND_RESYNC;
    case sync_pb::SyncEnums::ENABLE_SYNC_ON_ACCOUNT:
      return ENABLE_SYNC_ON_ACCOUNT;
    case sync_pb::SyncEnums::STOP_AND_RESTART_SYNC:
      return STOP_AND_RESTART_SYNC;
    case sync_pb::SyncEnums::DISABLE_SYNC_ON_CLIENT:
      return DISABLE_SYNC_ON_CLIENT;
    case sync_pb::SyncEnums::UNKNOWN_ACTION:
      return UNKNOWN_ACTION;
    default:
      NOTREACHED();
      return UNKNOWN_ACTION;
  }
}

// Returns true iff |message| is an initial GetUpdates request.
bool IsVeryFirstGetUpdates(const ClientToServerMessage& message) {
  if (!message.has_get_updates())
    return false;
  DCHECK_LT(0, message.get_updates().from_progress_marker_size());
  for (int i = 0; i < message.get_updates().from_progress_marker_size(); ++i) {
    if (!message.get_updates().from_progress_marker(i).token().empty())
      return false;
  }
  return true;
}

// Returns true iff |message| should contain a store birthday.
bool IsBirthdayRequired(const ClientToServerMessage& message) {
  if (message.has_clear_server_data())
    return false;
  if (message.has_commit())
    return true;
  if (message.has_get_updates())
    return !IsVeryFirstGetUpdates(message);
  NOTIMPLEMENTED();
  return true;
}

SyncProtocolError ErrorCodeToSyncProtocolError(
    const sync_pb::SyncEnums::ErrorType& error_type) {
  SyncProtocolError error;
  error.error_type = PBErrorTypeToSyncProtocolErrorType(error_type);
  if (error_type == sync_pb::SyncEnums::CLEAR_PENDING ||
      error_type == sync_pb::SyncEnums::NOT_MY_BIRTHDAY) {
    error.action = DISABLE_SYNC_ON_CLIENT;
  } else if (error_type == sync_pb::SyncEnums::CLIENT_DATA_OBSOLETE) {
    error.action = RESET_LOCAL_SYNC_DATA;
  } else if (error_type == sync_pb::SyncEnums::DISABLED_BY_ADMIN) {
    error.action = STOP_SYNC_FOR_DISABLED_ACCOUNT;
  }  // There is no other action we can compute for legacy server.
  return error;
}

}  // namespace

ModelTypeSet GetTypesToMigrate(const ClientToServerResponse& response) {
  ModelTypeSet to_migrate;
  for (int i = 0; i < response.migrated_data_type_id_size(); i++) {
    int field_number = response.migrated_data_type_id(i);
    ModelType model_type = GetModelTypeFromSpecificsFieldNumber(field_number);
    if (!IsRealDataType(model_type)) {
      DLOG(WARNING) << "Unknown field number " << field_number;
      continue;
    }
    to_migrate.Put(model_type);
  }
  return to_migrate;
}

SyncProtocolError ConvertErrorPBToSyncProtocolError(
    const sync_pb::ClientToServerResponse_Error& error) {
  SyncProtocolError sync_protocol_error;
  sync_protocol_error.error_type =
      PBErrorTypeToSyncProtocolErrorType(error.error_type());
  sync_protocol_error.error_description = error.error_description();
  sync_protocol_error.url = error.url();
  sync_protocol_error.action = PBActionToClientAction(error.action());

  if (error.error_data_type_ids_size() > 0) {
    // THROTTLED and PARTIAL_FAILURE are currently the only error codes
    // that uses |error_data_types|.
    // In both cases, |error_data_types| are throttled.
    for (int i = 0; i < error.error_data_type_ids_size(); ++i) {
      int field_number = error.error_data_type_ids(i);
      ModelType model_type =
          GetModelTypeFromSpecificsFieldNumber(field_number);
      if (!IsRealDataType(model_type)) {
        DLOG(WARNING) << "Unknown field number " << field_number;
        continue;
      }
      sync_protocol_error.error_data_types.Put(model_type);
    }
  }

  return sync_protocol_error;
}

// static
bool SyncerProtoUtil::VerifyResponseBirthday(
    const ClientToServerResponse& response,
    syncable::Directory* dir) {

  std::string local_birthday = dir->store_birthday();

  if (local_birthday.empty()) {
    if (!response.has_store_birthday()) {
      LOG(WARNING) << "Expected a birthday on first sync.";
      return false;
    }

    DVLOG(1) << "New store birthday: " << response.store_birthday();
    dir->set_store_birthday(response.store_birthday());
    return true;
  }

  // Error situation, but we're not stuck.
  if (!response.has_store_birthday()) {
    LOG(WARNING) << "No birthday in server response?";
    return true;
  }

  if (response.store_birthday() != local_birthday) {
    LOG(WARNING) << "Birthday changed, showing syncer stuck";
    return false;
  }

  return true;
}

// static
bool SyncerProtoUtil::IsSyncDisabledByAdmin(
    const sync_pb::ClientToServerResponse& response) {
  return (response.has_error_code() &&
          response.error_code() == sync_pb::SyncEnums::DISABLED_BY_ADMIN);
}

// static
SyncProtocolError SyncerProtoUtil::GetProtocolErrorFromResponse(
    const sync_pb::ClientToServerResponse& response,
    syncable::Directory* dir) {
  SyncProtocolError sync_protocol_error;

  // The DISABLED_BY_ADMIN error overrides other errors sent by the server.
  if (IsSyncDisabledByAdmin(response)) {
    sync_protocol_error.error_type = DISABLED_BY_ADMIN;
    sync_protocol_error.action = STOP_SYNC_FOR_DISABLED_ACCOUNT;
  } else if (!VerifyResponseBirthday(response, dir)) {
    // If sync isn't disabled, first check for a birthday mismatch error.
    if (response.error_code() == sync_pb::SyncEnums::CLIENT_DATA_OBSOLETE) {
      // Server indicates that client needs to reset sync data.
      sync_protocol_error.error_type = CLIENT_DATA_OBSOLETE;
      sync_protocol_error.action = RESET_LOCAL_SYNC_DATA;
    } else {
      sync_protocol_error.error_type = NOT_MY_BIRTHDAY;
      sync_protocol_error.action = DISABLE_SYNC_ON_CLIENT;
    }
  } else if (response.has_error()) {
    // This is a new server. Just get the error from the protocol.
    sync_protocol_error = ConvertErrorPBToSyncProtocolError(response.error());
  } else {
    // Legacy server implementation. Compute the error based on |error_code|.
    sync_protocol_error = ErrorCodeToSyncProtocolError(response.error_code());
  }
  return sync_protocol_error;
}

// static
void SyncerProtoUtil::AddRequestBirthday(syncable::Directory* dir,
                                         ClientToServerMessage* msg) {
  if (!dir->store_birthday().empty())
    msg->set_store_birthday(dir->store_birthday());
}

// static
void SyncerProtoUtil::AddBagOfChips(syncable::Directory* dir,
                                    ClientToServerMessage* msg) {
  msg->mutable_bag_of_chips()->ParseFromString(dir->bag_of_chips());
}

// static
void SyncerProtoUtil::SetProtocolVersion(ClientToServerMessage* msg) {
  const int current_version =
      ClientToServerMessage::default_instance().protocol_version();
  msg->set_protocol_version(current_version);
}

// static
bool SyncerProtoUtil::PostAndProcessHeaders(ServerConnectionManager* scm,
                                            sessions::SyncSession* session,
                                            const ClientToServerMessage& msg,
                                            ClientToServerResponse* response) {
  ServerConnectionManager::PostBufferParams params;
  DCHECK(msg.has_protocol_version());
  DCHECK_EQ(msg.protocol_version(),
            ClientToServerMessage::default_instance().protocol_version());
  msg.SerializeToString(&params.buffer_in);

  // Fills in params.buffer_out and params.response.
  if (!scm->PostBufferWithCachedAuth(&params)) {
    LOG(WARNING) << "Error posting from syncer:" << params.response;
    return false;
  }

  return response->ParseFromString(params.buffer_out);
}

base::TimeDelta SyncerProtoUtil::GetThrottleDelay(
    const ClientToServerResponse& response) {
  base::TimeDelta throttle_delay =
      base::TimeDelta::FromSeconds(kSyncDelayAfterThrottled);
  if (response.has_client_command()) {
    const sync_pb::ClientCommand& command = response.client_command();
    if (command.has_throttle_delay_seconds()) {
      throttle_delay =
          base::TimeDelta::FromSeconds(command.throttle_delay_seconds());
    }
  }
  return throttle_delay;
}

// static
SyncerError SyncerProtoUtil::PostClientToServerMessage(
    ClientToServerMessage* msg,
    ClientToServerResponse* response,
    SyncSession* session,
    ModelTypeSet* partial_failure_data_types) {
  CHECK(response);
  DCHECK(!msg->get_updates().has_from_timestamp());  // Deprecated.
  DCHECK(!msg->get_updates().has_requested_types());  // Deprecated.

  // Add must-have fields.
  SetProtocolVersion(msg);
  AddRequestBirthday(session->context()->directory(), msg);
  DCHECK(msg->has_store_birthday() || !IsBirthdayRequired(*msg));
  AddBagOfChips(session->context()->directory(), msg);
  msg->set_api_key(google_apis::GetAPIKey());
  msg->mutable_client_status()->CopyFrom(session->context()->client_status());
  msg->set_invalidator_client_id(session->context()->invalidator_client_id());

  syncable::Directory* dir = session->context()->directory();

  LogClientToServerMessage(*msg);
  if (!PostAndProcessHeaders(session->context()->connection_manager(), session,
                             *msg, response)) {
    // There was an error establishing communication with the server.
    // We can not proceed beyond this point.
    const HttpResponse::ServerConnectionCode server_status =
        session->context()->connection_manager()->server_status();

    DCHECK_NE(server_status, HttpResponse::NONE);
    DCHECK_NE(server_status, HttpResponse::SERVER_CONNECTION_OK);

    return ServerConnectionErrorAsSyncerError(server_status);
  }
  LogClientToServerResponse(*response);

  // Persist a bag of chips if it has been sent by the server.
  PersistBagOfChips(dir, *response);

  SyncProtocolError sync_protocol_error =
      GetProtocolErrorFromResponse(*response, dir);

  // Inform the delegate of the error we got.
  session->delegate()->OnSyncProtocolError(sync_protocol_error);

  // Update our state for any other commands we've received.
  if (response->has_client_command()) {
    const sync_pb::ClientCommand& command = response->client_command();
    if (command.has_max_commit_batch_size()) {
      session->context()->set_max_commit_batch_size(
          command.max_commit_batch_size());
    }

    if (command.has_set_sync_long_poll_interval()) {
      session->delegate()->OnReceivedLongPollIntervalUpdate(
          base::TimeDelta::FromSeconds(command.set_sync_long_poll_interval()));
    }

    if (command.has_set_sync_poll_interval()) {
      session->delegate()->OnReceivedShortPollIntervalUpdate(
          base::TimeDelta::FromSeconds(command.set_sync_poll_interval()));
    }

    if (command.has_sessions_commit_delay_seconds()) {
      std::map<ModelType, base::TimeDelta> delay_map;
      delay_map[SESSIONS] =
          base::TimeDelta::FromSeconds(command.sessions_commit_delay_seconds());
      session->delegate()->OnReceivedCustomNudgeDelays(delay_map);
    }

    if (command.has_client_invalidation_hint_buffer_size()) {
      session->delegate()->OnReceivedClientInvalidationHintBufferSize(
          command.client_invalidation_hint_buffer_size());
    }

    if (command.has_gu_retry_delay_seconds()) {
      session->delegate()->OnReceivedGuRetryDelay(
          base::TimeDelta::FromSeconds(command.gu_retry_delay_seconds()));
    }

    if (command.custom_nudge_delays_size() > 0) {
      // Note that because this happens after the sessions_commit_delay_seconds
      // handling, any SESSIONS value in this map will override the one in
      // sessions_commit_delay_seconds.
      std::map<ModelType, base::TimeDelta> delay_map;
      for (int i = 0; i < command.custom_nudge_delays_size(); ++i) {
        ModelType type = GetModelTypeFromSpecificsFieldNumber(
            command.custom_nudge_delays(i).datatype_id());
        if (ProtocolTypes().Has(type)) {
          delay_map[type] = base::TimeDelta::FromMilliseconds(
              command.custom_nudge_delays(i).delay_ms());
        }
      }
      session->delegate()->OnReceivedCustomNudgeDelays(delay_map);
    }
  }

  // Now do any special handling for the error type and decide on the return
  // value.
  switch (sync_protocol_error.error_type) {
    case UNKNOWN_ERROR:
      LOG(WARNING) << "Sync protocol out-of-date. The server is using a more "
                   << "recent version.";
      return SERVER_RETURN_UNKNOWN_ERROR;
    case SYNC_SUCCESS:
      LogResponseProfilingData(*response);
      return SYNCER_OK;
    case THROTTLED:
      if (sync_protocol_error.error_data_types.Empty()) {
        DLOG(WARNING) << "Client fully throttled by syncer.";
        session->delegate()->OnThrottled(GetThrottleDelay(*response));
      } else {
        DLOG(WARNING) << "Some types throttled by syncer.";
        session->delegate()->OnTypesThrottled(
            sync_protocol_error.error_data_types,
            GetThrottleDelay(*response));
      }
      return SERVER_RETURN_THROTTLED;
    case TRANSIENT_ERROR:
      return SERVER_RETURN_TRANSIENT_ERROR;
    case MIGRATION_DONE:
      LOG_IF(ERROR, 0 >= response->migrated_data_type_id_size())
          << "MIGRATION_DONE but no types specified.";
      session->delegate()->OnReceivedMigrationRequest(
          GetTypesToMigrate(*response));
      return SERVER_RETURN_MIGRATION_DONE;
    case CLEAR_PENDING:
      return SERVER_RETURN_CLEAR_PENDING;
    case NOT_MY_BIRTHDAY:
      return SERVER_RETURN_NOT_MY_BIRTHDAY;
    case DISABLED_BY_ADMIN:
      return SERVER_RETURN_DISABLED_BY_ADMIN;
    case PARTIAL_FAILURE:
      // This only happens when partial throttling during GetUpdates.
      if (!sync_protocol_error.error_data_types.Empty()) {
        DLOG(WARNING) << "Some types throttled by syncer during GetUpdates.";
        session->delegate()->OnTypesThrottled(
            sync_protocol_error.error_data_types, GetThrottleDelay(*response));
      }
      if (partial_failure_data_types != NULL) {
        *partial_failure_data_types = sync_protocol_error.error_data_types;
      }
      return SERVER_RETURN_PARTIAL_FAILURE;
    case CLIENT_DATA_OBSOLETE:
      return SERVER_RETURN_CLIENT_DATA_OBSOLETE;
    default:
      NOTREACHED();
      return UNSET;
  }
}

// static
bool SyncerProtoUtil::ShouldMaintainPosition(
    const sync_pb::SyncEntity& sync_entity) {
  // Maintain positions for bookmarks that are not server-defined top-level
  // folders.
  return GetModelType(sync_entity) == BOOKMARKS
      && !(sync_entity.folder() &&
           !sync_entity.server_defined_unique_tag().empty());
}

// static
bool SyncerProtoUtil::ShouldMaintainHierarchy(
    const sync_pb::SyncEntity& sync_entity) {
  // Maintain hierarchy for bookmarks or top-level items.
  return GetModelType(sync_entity) == BOOKMARKS ||
         sync_entity.parent_id_string() == "0";
}

// static
const std::string& SyncerProtoUtil::NameFromSyncEntity(
    const sync_pb::SyncEntity& entry) {
  if (entry.has_non_unique_name())
    return entry.non_unique_name();
  return entry.name();
}

// static
const std::string& SyncerProtoUtil::NameFromCommitEntryResponse(
    const sync_pb::CommitResponse_EntryResponse& entry) {
  if (entry.has_non_unique_name())
    return entry.non_unique_name();
  return entry.name();
}

// static
void SyncerProtoUtil::PersistBagOfChips(syncable::Directory* dir,
    const sync_pb::ClientToServerResponse& response) {
  if (!response.has_new_bag_of_chips())
    return;
  std::string bag_of_chips;
  if (response.new_bag_of_chips().SerializeToString(&bag_of_chips))
    dir->set_bag_of_chips(bag_of_chips);
}

std::string SyncerProtoUtil::SyncEntityDebugString(
    const sync_pb::SyncEntity& entry) {
  const std::string& mtime_str =
      GetTimeDebugString(ProtoTimeToTime(entry.mtime()));
  const std::string& ctime_str =
      GetTimeDebugString(ProtoTimeToTime(entry.ctime()));
  return base::StringPrintf(
      "id: %s, parent_id: %s, "
      "version: %" PRId64"d, "
      "mtime: %" PRId64"d (%s), "
      "ctime: %" PRId64"d (%s), "
      "name: %s, sync_timestamp: %" PRId64"d, "
      "%s ",
      entry.id_string().c_str(),
      entry.parent_id_string().c_str(),
      entry.version(),
      entry.mtime(), mtime_str.c_str(),
      entry.ctime(), ctime_str.c_str(),
      entry.name().c_str(), entry.sync_timestamp(),
      entry.deleted() ? "deleted, ":"");
}

namespace {
std::string GetUpdatesResponseString(
    const sync_pb::GetUpdatesResponse& response) {
  std::string output;
  output.append("GetUpdatesResponse:\n");
  for (int i = 0; i < response.entries_size(); i++) {
    output.append(SyncerProtoUtil::SyncEntityDebugString(response.entries(i)));
    output.append("\n");
  }
  return output;
}
}  // namespace

std::string SyncerProtoUtil::ClientToServerResponseDebugString(
    const ClientToServerResponse& response) {
  // Add more handlers as needed.
  std::string output;
  if (response.has_get_updates())
    output.append(GetUpdatesResponseString(response.get_updates()));
  return output;
}

}  // namespace syncer
