// 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/all_status.h"

#include <algorithm>

#include "base/logging.h"
#include "base/port.h"
#include "sync/engine/net/server_connection_manager.h"
#include "sync/engine/sync_cycle_event.h"
#include "sync/internal_api/public/base/model_type.h"

namespace syncer {

AllStatus::AllStatus() {
  status_.notifications_enabled = false;
  status_.cryptographer_ready = false;
  status_.crypto_has_pending_keys = false;
}

AllStatus::~AllStatus() {
}

SyncStatus AllStatus::CreateBlankStatus() const {
  // Status is initialized with the previous status value.  Variables
  // whose values accumulate (e.g. lifetime counters like updates_received)
  // are not to be cleared here.
  SyncStatus status = status_;
  status.encryption_conflicts = 0;
  status.hierarchy_conflicts = 0;
  status.server_conflicts = 0;
  status.committed_count = 0;
  return status;
}

SyncStatus AllStatus::CalcSyncing(const SyncCycleEvent &event) const {
  SyncStatus status = CreateBlankStatus();
  const sessions::SyncSessionSnapshot& snapshot = event.snapshot;
  status.encryption_conflicts = snapshot.num_encryption_conflicts();
  status.hierarchy_conflicts = snapshot.num_hierarchy_conflicts();
  status.server_conflicts = snapshot.num_server_conflicts();
  status.committed_count =
      snapshot.model_neutral_state().num_successful_commits;

  if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_BEGIN) {
    status.syncing = true;
  } else if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_ENDED) {
    status.syncing = false;
  }

  status.num_entries_by_type = snapshot.num_entries_by_type();
  status.num_to_delete_entries_by_type =
      snapshot.num_to_delete_entries_by_type();

  // Accumulate update count only once per session to avoid double-counting.
  if (event.what_happened == SyncCycleEvent::SYNC_CYCLE_ENDED) {
    status.updates_received +=
        snapshot.model_neutral_state().num_updates_downloaded_total;
    status.tombstone_updates_received +=
        snapshot.model_neutral_state().num_tombstone_updates_downloaded_total;
    status.reflected_updates_received +=
        snapshot.model_neutral_state().num_reflected_updates_downloaded_total;
    status.num_commits_total +=
        snapshot.model_neutral_state().num_successful_commits;
    status.num_local_overwrites_total +=
        snapshot.model_neutral_state().num_local_overwrites;
    status.num_server_overwrites_total +=
        snapshot.model_neutral_state().num_server_overwrites;
  }
  return status;
}

void AllStatus::OnSyncCycleEvent(const SyncCycleEvent& event) {
  ScopedStatusLock lock(this);
  switch (event.what_happened) {
    case SyncCycleEvent::SYNC_CYCLE_BEGIN:
    case SyncCycleEvent::STATUS_CHANGED:
    case SyncCycleEvent::SYNC_CYCLE_ENDED:
      status_ = CalcSyncing(event);
      break;
    default:
      LOG(ERROR) << "Unrecognized Syncer Event: " << event.what_happened;
      break;
  }
}

void AllStatus::OnActionableError(
    const SyncProtocolError& sync_protocol_error) {
  ScopedStatusLock lock(this);
  status_ = CreateBlankStatus();
  status_.sync_protocol_error = sync_protocol_error;
}

void AllStatus::OnRetryTimeChanged(base::Time retry_time) {
  ScopedStatusLock lock(this);
  status_.retry_time = retry_time;
}

void AllStatus::OnThrottledTypesChanged(ModelTypeSet throttled_types) {
  ScopedStatusLock lock(this);
  status_.throttled_types = throttled_types;
}

void AllStatus::OnMigrationRequested(ModelTypeSet) {}

void AllStatus::OnProtocolEvent(const ProtocolEvent&) {}

SyncStatus AllStatus::status() const {
  base::AutoLock lock(mutex_);
  return status_;
}

void AllStatus::SetNotificationsEnabled(bool notifications_enabled) {
  ScopedStatusLock lock(this);
  status_.notifications_enabled = notifications_enabled;
}

void AllStatus::IncrementNotificationsReceived() {
  ScopedStatusLock lock(this);
  ++status_.notifications_received;
}

void AllStatus::SetEncryptedTypes(ModelTypeSet types) {
  ScopedStatusLock lock(this);
  status_.encrypted_types = types;
}

void AllStatus::SetCryptographerReady(bool ready) {
  ScopedStatusLock lock(this);
  status_.cryptographer_ready = ready;
}

void AllStatus::SetCryptoHasPendingKeys(bool has_pending_keys) {
  ScopedStatusLock lock(this);
  status_.crypto_has_pending_keys = has_pending_keys;
}

void AllStatus::SetPassphraseType(PassphraseType type) {
  ScopedStatusLock lock(this);
  status_.passphrase_type = type;
}

void AllStatus::SetHasKeystoreKey(bool has_keystore_key) {
  ScopedStatusLock lock(this);
  status_.has_keystore_key = has_keystore_key;
}

void AllStatus::SetKeystoreMigrationTime(const base::Time& migration_time) {
  ScopedStatusLock lock(this);
  status_.keystore_migration_time = migration_time;
}

void AllStatus::SetSyncId(const std::string& sync_id) {
  ScopedStatusLock lock(this);
  status_.sync_id = sync_id;
}

void AllStatus::SetInvalidatorClientId(
    const std::string& invalidator_client_id) {
  ScopedStatusLock lock(this);
  status_.invalidator_client_id = invalidator_client_id;
}

void AllStatus::IncrementNudgeCounter(NudgeSource source) {
  ScopedStatusLock lock(this);
  switch(source) {
    case NUDGE_SOURCE_LOCAL_REFRESH:
      status_.nudge_source_local_refresh++;
      return;
    case NUDGE_SOURCE_LOCAL:
      status_.nudge_source_local++;
      return;
    case NUDGE_SOURCE_NOTIFICATION:
      status_.nudge_source_notification++;
      return;
    case NUDGE_SOURCE_UNKNOWN:
      break;
  }
  // If we're here, the source is most likely
  // NUDGE_SOURCE_UNKNOWN. That shouldn't happen.
  NOTREACHED();
}

ScopedStatusLock::ScopedStatusLock(AllStatus* allstatus)
    : allstatus_(allstatus) {
  allstatus->mutex_.Acquire();
}

ScopedStatusLock::~ScopedStatusLock() {
  allstatus_->mutex_.Release();
}

}  // namespace syncer
