// Copyright 2014 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_driver/data_type_manager_impl.h"

#include <algorithm>
#include <functional>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/strings/stringprintf.h"
#include "components/sync_driver/data_type_controller.h"
#include "components/sync_driver/data_type_encryption_handler.h"
#include "components/sync_driver/data_type_manager_observer.h"
#include "components/sync_driver/failed_data_types_handler.h"
#include "sync/internal_api/public/data_type_debug_info_listener.h"

namespace browser_sync {

namespace {

FailedDataTypesHandler::TypeErrorMap
GenerateCryptoErrorsForTypes(syncer::ModelTypeSet encrypted_types) {
  FailedDataTypesHandler::TypeErrorMap crypto_errors;
  for (syncer::ModelTypeSet::Iterator iter = encrypted_types.First();
         iter.Good(); iter.Inc()) {
    crypto_errors[iter.Get()] = syncer::SyncError(
        FROM_HERE,
        syncer::SyncError::CRYPTO_ERROR,
        "",
        iter.Get());
  }
  return crypto_errors;
}

}  // namespace

DataTypeManagerImpl::AssociationTypesInfo::AssociationTypesInfo() {}
DataTypeManagerImpl::AssociationTypesInfo::~AssociationTypesInfo() {}

DataTypeManagerImpl::DataTypeManagerImpl(
    const base::Closure& unrecoverable_error_method,
    const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>&
        debug_info_listener,
    const DataTypeController::TypeMap* controllers,
    const browser_sync::DataTypeEncryptionHandler* encryption_handler,
    BackendDataTypeConfigurer* configurer,
    DataTypeManagerObserver* observer,
    browser_sync::FailedDataTypesHandler* failed_data_types_handler)
    : configurer_(configurer),
      controllers_(controllers),
      state_(DataTypeManager::STOPPED),
      needs_reconfigure_(false),
      last_configure_reason_(syncer::CONFIGURE_REASON_UNKNOWN),
      debug_info_listener_(debug_info_listener),
      model_association_manager_(controllers, this),
      observer_(observer),
      failed_data_types_handler_(failed_data_types_handler),
      encryption_handler_(encryption_handler),
      unrecoverable_error_method_(unrecoverable_error_method),
      weak_ptr_factory_(this) {
  DCHECK(failed_data_types_handler_);
  DCHECK(configurer_);
  DCHECK(observer_);
}

DataTypeManagerImpl::~DataTypeManagerImpl() {}

void DataTypeManagerImpl::Configure(syncer::ModelTypeSet desired_types,
                                    syncer::ConfigureReason reason) {
  if (reason == syncer::CONFIGURE_REASON_BACKUP_ROLLBACK)
    desired_types.PutAll(syncer::ControlTypes());
  else
    desired_types.PutAll(syncer::CoreTypes());

  // Only allow control types and types that have controllers.
  syncer::ModelTypeSet filtered_desired_types;
  for (syncer::ModelTypeSet::Iterator type = desired_types.First();
      type.Good(); type.Inc()) {
    DataTypeController::TypeMap::const_iterator iter =
        controllers_->find(type.Get());
    if (syncer::IsControlType(type.Get()) ||
        iter != controllers_->end()) {
      if (iter != controllers_->end()) {
        if (!iter->second->ReadyForStart()) {
          // Add the type to the unready types set to prevent purging it. It's
          // up to the datatype controller to, if necessary, explicitly
          // mark the type as broken to trigger a purge.
          syncer::SyncError error(FROM_HERE,
                                  syncer::SyncError::UNREADY_ERROR,
                                  "Datatype not ready at config time.",
                                  type.Get());
          std::map<syncer::ModelType, syncer::SyncError> errors;
          errors[type.Get()] = error;
          failed_data_types_handler_->UpdateFailedDataTypes(errors);
        } else {
          failed_data_types_handler_->ResetUnreadyErrorFor(type.Get());
        }
      }
      filtered_desired_types.Put(type.Get());
    }
  }
  ConfigureImpl(filtered_desired_types, reason);
}

void DataTypeManagerImpl::PurgeForMigration(
    syncer::ModelTypeSet undesired_types,
    syncer::ConfigureReason reason) {
  syncer::ModelTypeSet remainder = Difference(last_requested_types_,
                                              undesired_types);
  ConfigureImpl(remainder, reason);
}

void DataTypeManagerImpl::ConfigureImpl(
    syncer::ModelTypeSet desired_types,
    syncer::ConfigureReason reason) {
  DCHECK_NE(reason, syncer::CONFIGURE_REASON_UNKNOWN);
  DVLOG(1) << "Configuring for " << syncer::ModelTypeSetToString(desired_types)
           << " with reason " << reason;
  if (state_ == STOPPING) {
    // You can not set a configuration while stopping.
    LOG(ERROR) << "Configuration set while stopping.";
    return;
  }

  // TODO(zea): consider not performing a full configuration once there's a
  // reliable way to determine if the requested set of enabled types matches the
  // current set.

  last_requested_types_ = desired_types;
  last_configure_reason_ = reason;
  // Only proceed if we're in a steady state or retrying.
  if (state_ != STOPPED && state_ != CONFIGURED && state_ != RETRYING) {
    DVLOG(1) << "Received configure request while configuration in flight. "
             << "Postponing until current configuration complete.";
    needs_reconfigure_ = true;
    return;
  }

  Restart(reason);
}

BackendDataTypeConfigurer::DataTypeConfigStateMap
DataTypeManagerImpl::BuildDataTypeConfigStateMap(
    const syncer::ModelTypeSet& types_being_configured) const {
  // 1. Get the failed types (due to fatal, crypto, and unready errors).
  // 2. Add the difference between last_requested_types_ and the failed types
  //    as CONFIGURE_INACTIVE.
  // 3. Flip |types_being_configured| to CONFIGURE_ACTIVE.
  // 4. Set non-enabled user types as DISABLED.
  // 5. Set the fatal, crypto, and unready types to their respective states.
  syncer::ModelTypeSet error_types =
      failed_data_types_handler_->GetFailedTypes();
  syncer::ModelTypeSet fatal_types =
      failed_data_types_handler_->GetFatalErrorTypes();
  syncer::ModelTypeSet crypto_types =
      failed_data_types_handler_->GetCryptoErrorTypes();
  syncer::ModelTypeSet unready_types=
      failed_data_types_handler_->GetUnreadyErrorTypes();

  // Types with persistence errors are only purged/resynced when they're
  // actively being configured.
  syncer::ModelTypeSet persistence_types =
      failed_data_types_handler_->GetPersistenceErrorTypes();
  persistence_types.RetainAll(types_being_configured);

  // Types with unready errors do not count as unready if they've been disabled.
  unready_types.RetainAll(last_requested_types_);

  syncer::ModelTypeSet enabled_types = last_requested_types_;
  enabled_types.RemoveAll(error_types);
  syncer::ModelTypeSet disabled_types =
      syncer::Difference(
          syncer::Union(syncer::UserTypes(), syncer::ControlTypes()),
          enabled_types);
  syncer::ModelTypeSet to_configure = syncer::Intersection(
      enabled_types, types_being_configured);
  DVLOG(1) << "Enabling: " << syncer::ModelTypeSetToString(enabled_types);
  DVLOG(1) << "Configuring: " << syncer::ModelTypeSetToString(to_configure);
  DVLOG(1) << "Disabling: " << syncer::ModelTypeSetToString(disabled_types);

  BackendDataTypeConfigurer::DataTypeConfigStateMap config_state_map;
  BackendDataTypeConfigurer::SetDataTypesState(
      BackendDataTypeConfigurer::CONFIGURE_INACTIVE, enabled_types,
      &config_state_map);
  BackendDataTypeConfigurer::SetDataTypesState(
      BackendDataTypeConfigurer::CONFIGURE_ACTIVE, to_configure,
      &config_state_map);
  BackendDataTypeConfigurer::SetDataTypesState(
      BackendDataTypeConfigurer::CONFIGURE_CLEAN, persistence_types,
        &config_state_map);
  BackendDataTypeConfigurer::SetDataTypesState(
      BackendDataTypeConfigurer::DISABLED, disabled_types,
      &config_state_map);
  BackendDataTypeConfigurer::SetDataTypesState(
      BackendDataTypeConfigurer::FATAL, fatal_types,
      &config_state_map);
  BackendDataTypeConfigurer::SetDataTypesState(
      BackendDataTypeConfigurer::CRYPTO, crypto_types,
        &config_state_map);
  BackendDataTypeConfigurer::SetDataTypesState(
      BackendDataTypeConfigurer::UNREADY, unready_types,
        &config_state_map);
  return config_state_map;
}

void DataTypeManagerImpl::Restart(syncer::ConfigureReason reason) {
  DVLOG(1) << "Restarting...";

  // Check for new or resolved data type crypto errors.
  if (encryption_handler_->IsPassphraseRequired()) {
    syncer::ModelTypeSet encrypted_types =
        encryption_handler_->GetEncryptedDataTypes();
    encrypted_types.RetainAll(last_requested_types_);
    encrypted_types.RemoveAll(
        failed_data_types_handler_->GetCryptoErrorTypes());
    FailedDataTypesHandler::TypeErrorMap crypto_errors =
        GenerateCryptoErrorsForTypes(encrypted_types);
    failed_data_types_handler_->UpdateFailedDataTypes(crypto_errors);
  } else {
    failed_data_types_handler_->ResetCryptoErrors();
  }

  syncer::ModelTypeSet failed_types =
      failed_data_types_handler_->GetFailedTypes();
  syncer::ModelTypeSet enabled_types =
      syncer::Difference(last_requested_types_, failed_types);

  last_restart_time_ = base::Time::Now();
  configuration_stats_.clear();

  DCHECK(state_ == STOPPED || state_ == CONFIGURED || state_ == RETRYING);

  // Starting from a "steady state" (stopped or configured) state
  // should send a start notification.
  if (state_ == STOPPED || state_ == CONFIGURED)
    NotifyStart();

  model_association_manager_.Initialize(enabled_types);

  download_types_queue_ = PrioritizeTypes(enabled_types);
  association_types_queue_ = std::queue<AssociationTypesInfo>();

  // Tell the backend about the new set of data types we wish to sync.
  // The task will be invoked when updates are downloaded.
  state_ = DOWNLOAD_PENDING;
  configurer_->ConfigureDataTypes(
      reason,
      BuildDataTypeConfigStateMap(download_types_queue_.front()),
      base::Bind(&DataTypeManagerImpl::DownloadReady,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Time::Now(),
                 download_types_queue_.front(),
                 syncer::ModelTypeSet()),
      base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
                 weak_ptr_factory_.GetWeakPtr()));
}

syncer::ModelTypeSet DataTypeManagerImpl::GetPriorityTypes() const {
  syncer::ModelTypeSet high_priority_types;
  high_priority_types.PutAll(syncer::PriorityCoreTypes());
  high_priority_types.PutAll(syncer::PriorityUserTypes());
  return high_priority_types;
}

TypeSetPriorityList DataTypeManagerImpl::PrioritizeTypes(
    const syncer::ModelTypeSet& types) {
  syncer::ModelTypeSet high_priority_types = GetPriorityTypes();
  high_priority_types.RetainAll(types);

  syncer::ModelTypeSet low_priority_types =
      syncer::Difference(types, high_priority_types);

  TypeSetPriorityList result;
  if (!high_priority_types.Empty())
    result.push(high_priority_types);
  if (!low_priority_types.Empty())
    result.push(low_priority_types);

  // Could be empty in case of purging for migration, sync nothing, etc.
  // Configure empty set to purge data from backend.
  if (result.empty())
    result.push(syncer::ModelTypeSet());

  return result;
}

void DataTypeManagerImpl::ProcessReconfigure() {
  DCHECK(needs_reconfigure_);

  // Wait for current download and association to finish.
  if (!(download_types_queue_.empty() && association_types_queue_.empty()))
    return;

  // An attempt was made to reconfigure while we were already configuring.
  // This can be because a passphrase was accepted or the user changed the
  // set of desired types. Either way, |last_requested_types_| will contain
  // the most recent set of desired types, so we just call configure.
  // Note: we do this whether or not GetControllersNeedingStart is true,
  // because we may need to stop datatypes.
  DVLOG(1) << "Reconfiguring due to previous configure attempt occuring while"
           << " busy.";

  // Note: ConfigureImpl is called directly, rather than posted, in order to
  // ensure that any purging/unapplying/journaling happens while the set of
  // failed types is still up to date. If stack unwinding were to be done
  // via PostTask, the failed data types may be reset before the purging was
  // performed.
  state_ = RETRYING;
  needs_reconfigure_ = false;
  ConfigureImpl(last_requested_types_, last_configure_reason_);
}

void DataTypeManagerImpl::OnDownloadRetry() {
  DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);
  observer_->OnConfigureRetry();
}

void DataTypeManagerImpl::DownloadReady(
    base::Time download_start_time,
    syncer::ModelTypeSet types_to_download,
    syncer::ModelTypeSet high_priority_types_before,
    syncer::ModelTypeSet first_sync_types,
    syncer::ModelTypeSet failed_configuration_types) {
  DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);

  // Persistence errors are reset after each backend configuration attempt
  // during which they would have been purged.
  failed_data_types_handler_->ResetPersistenceErrorsFrom(types_to_download);

  // Ignore |failed_configuration_types| if we need to reconfigure
  // anyway.
  if (needs_reconfigure_) {
    download_types_queue_ = TypeSetPriorityList();
    ProcessReconfigure();
    return;
  }

  if (!failed_configuration_types.Empty()) {
    if (!unrecoverable_error_method_.is_null())
      unrecoverable_error_method_.Run();
    std::string error_msg =
        "Configuration failed for types " +
        syncer::ModelTypeSetToString(failed_configuration_types);
    syncer::SyncError error(FROM_HERE,
                            syncer::SyncError::UNRECOVERABLE_ERROR,
                            error_msg,
                            failed_configuration_types.First().Get());
    Abort(UNRECOVERABLE_ERROR, error);
    return;
  }

  state_ = CONFIGURING;

  // Pop and associate download-ready types.
  syncer::ModelTypeSet ready_types = types_to_download;
  download_types_queue_.pop();
  syncer::ModelTypeSet new_types_to_download;
  if (!download_types_queue_.empty())
    new_types_to_download = download_types_queue_.front();

  AssociationTypesInfo association_info;
  association_info.types = ready_types;
  association_info.first_sync_types = first_sync_types;
  association_info.download_start_time = download_start_time;
  association_info.download_ready_time = base::Time::Now();
  association_info.high_priority_types_before = high_priority_types_before;
  association_types_queue_.push(association_info);
  if (association_types_queue_.size() == 1u)
    StartNextAssociation();

  // Download types of low priority while configuring types of high priority.
  if (!new_types_to_download.Empty()) {
    configurer_->ConfigureDataTypes(
        last_configure_reason_,
        BuildDataTypeConfigStateMap(new_types_to_download),
        base::Bind(&DataTypeManagerImpl::DownloadReady,
                   weak_ptr_factory_.GetWeakPtr(),
                   base::Time::Now(),
                   new_types_to_download,
                   syncer::Union(ready_types, high_priority_types_before)),
        base::Bind(&DataTypeManagerImpl::OnDownloadRetry,
                   weak_ptr_factory_.GetWeakPtr()));
  }
}

void DataTypeManagerImpl::StartNextAssociation() {
  CHECK(!association_types_queue_.empty());

  association_types_queue_.front().association_request_time =
      base::Time::Now();
  model_association_manager_.StartAssociationAsync(
      association_types_queue_.front().types);
}

void DataTypeManagerImpl::OnSingleDataTypeWillStop(
    syncer::ModelType type) {
  configurer_->DeactivateDataType(type);
}

void DataTypeManagerImpl::OnSingleDataTypeAssociationDone(
    syncer::ModelType type,
    const syncer::DataTypeAssociationStats& association_stats) {
  DCHECK(!association_types_queue_.empty());
  DataTypeController::TypeMap::const_iterator c_it = controllers_->find(type);
  DCHECK(c_it != controllers_->end());
  if (c_it->second->state() == DataTypeController::RUNNING) {
    // Tell the backend about the change processor for this type so it can
    // begin routing changes to it.
    configurer_->ActivateDataType(type, c_it->second->model_safe_group(),
                                  c_it->second->GetChangeProcessor());
  }

  if (!debug_info_listener_.IsInitialized())
    return;

  AssociationTypesInfo& info = association_types_queue_.front();
  configuration_stats_.push_back(syncer::DataTypeConfigurationStats());
  configuration_stats_.back().model_type = type;
  configuration_stats_.back().association_stats = association_stats;
  if (info.types.Has(type)) {
    // Times in |info| only apply to non-slow types.
    configuration_stats_.back().download_wait_time =
        info.download_start_time - last_restart_time_;
    if (info.first_sync_types.Has(type)) {
      configuration_stats_.back().download_time =
          info.download_ready_time - info.download_start_time;
    }
    configuration_stats_.back().association_wait_time_for_high_priority =
        info.association_request_time - info.download_ready_time;
    configuration_stats_.back().high_priority_types_configured_before =
        info.high_priority_types_before;
    configuration_stats_.back().same_priority_types_configured_before =
        info.configured_types;
    info.configured_types.Put(type);
  }
}

void DataTypeManagerImpl::OnModelAssociationDone(
    const DataTypeManager::ConfigureResult& result) {
  DCHECK(state_ == STOPPING || state_ == CONFIGURING);

  if (state_ == STOPPING)
    return;

  // Don't reconfigure due to failed data types if we have an unrecoverable
  // error or have already aborted.
  if (result.status  == PARTIAL_SUCCESS) {
    if (!result.needs_crypto.Empty()) {
      needs_reconfigure_ = true;
      syncer::ModelTypeSet encrypted_types = result.needs_crypto;
      encrypted_types.RemoveAll(
          failed_data_types_handler_->GetCryptoErrorTypes());
      FailedDataTypesHandler::TypeErrorMap crypto_errors =
          GenerateCryptoErrorsForTypes(encrypted_types);
      failed_data_types_handler_->UpdateFailedDataTypes(crypto_errors);
    }
    if (!result.failed_data_types.empty()) {
      needs_reconfigure_ = true;
      failed_data_types_handler_->UpdateFailedDataTypes(
          result.failed_data_types);
    }
  }

  // Ignore abort/unrecoverable error if we need to reconfigure anyways.
  if (needs_reconfigure_) {
    association_types_queue_ = std::queue<AssociationTypesInfo>();
    ProcessReconfigure();
    return;
  }

  if (result.status == ABORTED || result.status == UNRECOVERABLE_ERROR) {
    Abort(result.status, result.failed_data_types.size() >= 1 ?
                         result.failed_data_types.begin()->second :
                         syncer::SyncError());
    return;
  }

  DCHECK(result.status == PARTIAL_SUCCESS || result.status == OK);
  DCHECK(result.status != OK ||
         (result.needs_crypto.Empty() && result.failed_data_types.empty()));

  // It's possible this is a retry to disable failed types, in which case
  // the association would be SUCCESS, but the overall configuration should
  // still be PARTIAL_SUCCESS.
  syncer::ModelTypeSet failed_data_types =
      failed_data_types_handler_->GetFailedTypes();
  ConfigureStatus status = result.status;
  if (!syncer::Intersection(last_requested_types_,
                            failed_data_types).Empty() && result.status == OK) {
    status = PARTIAL_SUCCESS;
  }

  association_types_queue_.pop();
  if (!association_types_queue_.empty()) {
    StartNextAssociation();
  } else if (download_types_queue_.empty()) {
    state_ = CONFIGURED;
    ConfigureResult configure_result(status,
                                     result.requested_types,
                                     failed_data_types_handler_->GetAllErrors(),
                                     result.unfinished_data_types,
                                     result.needs_crypto);
    NotifyDone(configure_result);
  }
}

void DataTypeManagerImpl::Stop() {
  if (state_ == STOPPED)
    return;

  bool need_to_notify =
      state_ == DOWNLOAD_PENDING || state_ == CONFIGURING;
  StopImpl();

  if (need_to_notify) {
    ConfigureResult result(ABORTED,
                           last_requested_types_,
                           std::map<syncer::ModelType, syncer::SyncError>(),
                           syncer::ModelTypeSet(),
                           syncer::ModelTypeSet());
    NotifyDone(result);
  }
}

void DataTypeManagerImpl::Abort(ConfigureStatus status,
                                const syncer::SyncError& error) {
  DCHECK(state_ == DOWNLOAD_PENDING || state_ == CONFIGURING);

  StopImpl();

  DCHECK_NE(OK, status);
  std::map<syncer::ModelType, syncer::SyncError> errors;
  if (error.IsSet())
    errors[error.model_type()] = error;
  ConfigureResult result(status,
                         last_requested_types_,
                         errors,
                         syncer::ModelTypeSet(),
                         syncer::ModelTypeSet());
  NotifyDone(result);
}

void DataTypeManagerImpl::StopImpl() {
  state_ = STOPPING;

  // Invalidate weak pointer to drop download callbacks.
  weak_ptr_factory_.InvalidateWeakPtrs();

  // Stop all data types. This may trigger association callback but the
  // callback will do nothing because state is set to STOPPING above.
  model_association_manager_.Stop();

  state_ = STOPPED;
}

void DataTypeManagerImpl::NotifyStart() {
  observer_->OnConfigureStart();
}

void DataTypeManagerImpl::NotifyDone(const ConfigureResult& result) {
  AddToConfigureTime();

  DVLOG(1) << "Total time spent configuring: "
           << configure_time_delta_.InSecondsF() << "s";
  switch (result.status) {
    case DataTypeManager::OK:
      DVLOG(1) << "NotifyDone called with result: OK";
      UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.OK",
                               configure_time_delta_);
      if (debug_info_listener_.IsInitialized() &&
          !configuration_stats_.empty()) {
        debug_info_listener_.Call(
            FROM_HERE,
            &syncer::DataTypeDebugInfoListener::OnDataTypeConfigureComplete,
            configuration_stats_);
      }
      configuration_stats_.clear();
      break;
    case DataTypeManager::ABORTED:
      DVLOG(1) << "NotifyDone called with result: ABORTED";
      UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.ABORTED",
                               configure_time_delta_);
      break;
    case DataTypeManager::UNRECOVERABLE_ERROR:
      DVLOG(1) << "NotifyDone called with result: UNRECOVERABLE_ERROR";
      UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.UNRECOVERABLE_ERROR",
                               configure_time_delta_);
      break;
    case DataTypeManager::PARTIAL_SUCCESS:
      DVLOG(1) << "NotifyDone called with result: PARTIAL_SUCCESS";
      UMA_HISTOGRAM_LONG_TIMES("Sync.ConfigureTime_Long.PARTIAL_SUCCESS",
                               configure_time_delta_);
      break;
    default:
      NOTREACHED();
      break;
  }
  observer_->OnConfigureDone(result);
}

DataTypeManager::State DataTypeManagerImpl::state() const {
  return state_;
}

void DataTypeManagerImpl::AddToConfigureTime() {
  DCHECK(!last_restart_time_.is_null());
  configure_time_delta_ += (base::Time::Now() - last_restart_time_);
}

}  // namespace browser_sync
