// 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 "chrome/browser/sync/glue/model_association_manager.h"

#include <algorithm>
#include <functional>

#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "sync/internal_api/public/base/model_type.h"

using content::BrowserThread;
using syncer::ModelTypeSet;

namespace browser_sync {
// The amount of time we wait for a datatype to load. If the type has
// not finished loading we move on to the next type. Once this type
// finishes loading we will do a configure to associate this type. Note
// that in most cases types finish loading before this timeout.
const int64 kDataTypeLoadWaitTimeInSeconds = 120;
namespace {

static const syncer::ModelType kStartOrder[] = {
  syncer::NIGORI,               //  Listed for completeness.
  syncer::DEVICE_INFO,          //  Listed for completeness.
  syncer::EXPERIMENTS,          //  Listed for completeness.
  syncer::PROXY_TABS,           //  Listed for completeness.
  syncer::BOOKMARKS,            //  UI thread datatypes.
  syncer::MANAGED_USERS,        //  Syncing managed users on initial login might
                                //  block creating a new managed user, so we
                                //  want to do it early.
  syncer::PREFERENCES,
  syncer::PRIORITY_PREFERENCES,
  syncer::EXTENSIONS,
  syncer::APPS,
  syncer::THEMES,
  syncer::SEARCH_ENGINES,
  syncer::SESSIONS,
  syncer::APP_NOTIFICATIONS,
  syncer::DICTIONARY,
  syncer::FAVICON_IMAGES,
  syncer::FAVICON_TRACKING,
  syncer::MANAGED_USER_SETTINGS,
  syncer::ARTICLES,
  syncer::AUTOFILL,             // Non-UI thread datatypes.
  syncer::AUTOFILL_PROFILE,
  syncer::EXTENSION_SETTINGS,
  syncer::APP_SETTINGS,
  syncer::TYPED_URLS,
  syncer::PASSWORDS,
  syncer::HISTORY_DELETE_DIRECTIVES,
  syncer::SYNCED_NOTIFICATIONS,
};

COMPILE_ASSERT(arraysize(kStartOrder) ==
               syncer::MODEL_TYPE_COUNT - syncer::FIRST_REAL_MODEL_TYPE,
               kStartOrder_IncorrectSize);

// Comparator used when sorting data type controllers.
class SortComparator : public std::binary_function<DataTypeController*,
                                                   DataTypeController*,
                                                   bool> {
 public:
  explicit SortComparator(std::map<syncer::ModelType, int>* order)
      : order_(order) { }

  // Returns true if lhs precedes rhs.
  bool operator() (DataTypeController* lhs, DataTypeController* rhs) {
    return (*order_)[lhs->type()] < (*order_)[rhs->type()];
  }

 private:
  std::map<syncer::ModelType, int>* order_;
};

syncer::DataTypeAssociationStats BuildAssociationStatsFromMergeResults(
    const syncer::SyncMergeResult& local_merge_result,
    const syncer::SyncMergeResult& syncer_merge_result,
    const base::TimeDelta& association_wait_time,
    const base::TimeDelta& association_time) {
  DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type());
  syncer::DataTypeAssociationStats stats;
  stats.had_error = local_merge_result.error().IsSet() ||
                    syncer_merge_result.error().IsSet();
  stats.num_local_items_before_association =
      local_merge_result.num_items_before_association();
  stats.num_sync_items_before_association =
      syncer_merge_result.num_items_before_association();
  stats.num_local_items_after_association =
      local_merge_result.num_items_after_association();
  stats.num_sync_items_after_association =
      syncer_merge_result.num_items_after_association();
  stats.num_local_items_added =
      local_merge_result.num_items_added();
  stats.num_local_items_deleted =
      local_merge_result.num_items_deleted();
  stats.num_local_items_modified =
      local_merge_result.num_items_modified();
  stats.local_version_pre_association =
      local_merge_result.pre_association_version();
  stats.num_sync_items_added =
      syncer_merge_result.num_items_added();
  stats.num_sync_items_deleted =
      syncer_merge_result.num_items_deleted();
  stats.num_sync_items_modified =
      syncer_merge_result.num_items_modified();
  stats.sync_version_pre_association =
      syncer_merge_result.pre_association_version();
  stats.association_wait_time = association_wait_time;
  stats.association_time = association_time;
  return stats;
}

}  // namespace

ModelAssociationManager::ModelAssociationManager(
    const DataTypeController::TypeMap* controllers,
    ModelAssociationResultProcessor* processor)
    : state_(IDLE),
      currently_associating_(NULL),
      controllers_(controllers),
      result_processor_(processor),
      weak_ptr_factory_(this) {

  // Ensure all data type controllers are stopped.
  for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
       it != controllers_->end(); ++it) {
    DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state());
  }

  // Build a ModelType -> order map for sorting.
  for (int i = 0; i < static_cast<int>(arraysize(kStartOrder)); i++)
    start_order_[kStartOrder[i]] = i;
}

ModelAssociationManager::~ModelAssociationManager() {
}

void ModelAssociationManager::Initialize(syncer::ModelTypeSet desired_types) {
  // TODO(tim): Bug 134550.  CHECKing to ensure no reentrancy on dev channel.
  // Remove this.
  CHECK_EQ(state_, IDLE);
  needs_start_.clear();
  needs_stop_.clear();
  failed_data_types_info_.clear();
  associating_types_.Clear();
  needs_crypto_types_.Clear();
  state_ = INITIALIZED_TO_CONFIGURE;

  DVLOG(1) << "ModelAssociationManager: Initializing for "
           << syncer::ModelTypeSetToString(desired_types);

  // Stop the types that are still loading from the previous configuration.
  // If they are enabled we will start them here once again.
  for (std::vector<DataTypeController*>::const_iterator it =
           pending_model_load_.begin();
       it != pending_model_load_.end();
       ++it) {
    DVLOG(1) << "ModelAssociationManager: Stopping "
             << (*it)->name()
             << " before initialization";
    (*it)->Stop();
  }

  pending_model_load_.clear();
  waiting_to_associate_.clear();
  currently_associating_ = NULL;

  // Add any data type controllers into that needs_stop_ list that are
  // currently MODEL_STARTING, ASSOCIATING, RUNNING or DISABLED.
  for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
       it != controllers_->end(); ++it) {
    DataTypeController* dtc = (*it).second.get();
    if (!desired_types.Has(dtc->type()) &&
        (dtc->state() == DataTypeController::MODEL_STARTING ||
         dtc->state() == DataTypeController::ASSOCIATING ||
         dtc->state() == DataTypeController::RUNNING ||
         dtc->state() == DataTypeController::DISABLED)) {
      needs_stop_.push_back(dtc);
      DVLOG(1) << "ModelTypeToString: Will stop " << dtc->name();
    }
  }
  // Sort these according to kStartOrder.
  std::sort(needs_stop_.begin(),
            needs_stop_.end(),
            SortComparator(&start_order_));
}

void ModelAssociationManager::StartAssociationAsync(
    const syncer::ModelTypeSet& types_to_associate) {
  DCHECK(state_ == INITIALIZED_TO_CONFIGURE || state_ == IDLE);
  state_ = CONFIGURING;

  // Calculate |needs_start_| list.
  associating_types_ = types_to_associate;
  GetControllersNeedingStart(&needs_start_);
  // Sort these according to kStartOrder.
  std::sort(needs_start_.begin(),
            needs_start_.end(),
            SortComparator(&start_order_));

  DVLOG(1) << "ModelAssociationManager: Going to start model association";
  association_start_time_ = base::Time::Now();
  LoadModelForNextType();
}

void ModelAssociationManager::ResetForReconfiguration() {
  state_ = IDLE;
  DVLOG(1) << "ModelAssociationManager: Reseting for reconfiguration";
  needs_start_.clear();
  needs_stop_.clear();
  associating_types_.Clear();
  failed_data_types_info_.clear();
  needs_crypto_types_.Clear();
}

void ModelAssociationManager::StopDisabledTypes() {
  DVLOG(1) << "ModelAssociationManager: Stopping disabled types.";
  // Stop requested data types.
  for (size_t i = 0; i < needs_stop_.size(); ++i) {
    DVLOG(1) << "ModelAssociationManager: Stopping " << needs_stop_[i]->name();
    needs_stop_[i]->Stop();
  }
  needs_stop_.clear();
}

void ModelAssociationManager::Stop() {
  bool need_to_call_model_association_done = false;
  DVLOG(1) << "ModelAssociationManager: Stopping MAM";
  if (state_ == CONFIGURING) {
    DVLOG(1) << "ModelAssociationManager: In the middle of configuration while"
             << " stopping";
    state_ = ABORTED;
    DCHECK(currently_associating_ != NULL ||
           needs_start_.size() > 0 ||
           pending_model_load_.size() > 0 ||
           waiting_to_associate_.size() > 0);

    if (currently_associating_) {
      TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation",
                             currently_associating_,
                             "DataType",
                             ModelTypeToString(currently_associating_->type()));
      DVLOG(1) << "ModelAssociationManager: stopping "
               << currently_associating_->name();
      currently_associating_->Stop();
    } else {
      // DTCs in other lists would be stopped below.
      state_ = IDLE;
    }

    DCHECK_EQ(IDLE, state_);

    // We are in the midle of model association. We need to inform the caller
    // so the caller can send notificationst to PSS layer.
    need_to_call_model_association_done = true;
  }

  // Now continue stopping any types that have already started.
  DCHECK(state_ == IDLE ||
         state_ == INITIALIZED_TO_CONFIGURE);
  for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
       it != controllers_->end(); ++it) {
    DataTypeController* dtc = (*it).second.get();
    if (dtc->state() != DataTypeController::NOT_RUNNING &&
        dtc->state() != DataTypeController::STOPPING) {
      dtc->Stop();
      DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name();
    }
  }

  DataTypeManager::ConfigureResult result(DataTypeManager::ABORTED,
                                          associating_types_,
                                          failed_data_types_info_,
                                          syncer::ModelTypeSet(),
                                          needs_crypto_types_);
  failed_data_types_info_.clear();
  needs_crypto_types_.Clear();
  if (need_to_call_model_association_done) {
    DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone";
    result_processor_->OnModelAssociationDone(result);
  }
}

bool ModelAssociationManager::GetControllersNeedingStart(
    std::vector<DataTypeController*>* needs_start) {
  DVLOG(1) << "ModelAssociationManager: GetControllersNeedingStart";
  // Add any data type controllers into the needs_start_ list that are
  // currently NOT_RUNNING or STOPPING.
  bool found_any = false;
  for (ModelTypeSet::Iterator it = associating_types_.First();
       it.Good(); it.Inc()) {
    DataTypeController::TypeMap::const_iterator dtc =
        controllers_->find(it.Get());
    if (dtc != controllers_->end() &&
        (dtc->second->state() == DataTypeController::NOT_RUNNING ||
         dtc->second->state() == DataTypeController::STOPPING)) {
      found_any = true;
      if (needs_start)
        needs_start->push_back(dtc->second.get());
      if (dtc->second->state() == DataTypeController::DISABLED) {
        DVLOG(1) << "ModelAssociationManager: Found "\
                << syncer::ModelTypeToString(dtc->second->type())
                 << " in disabled state.";
      }
    }
  }
  return found_any;
}

void ModelAssociationManager::AppendToFailedDatatypesAndLogError(
    DataTypeController::StartResult result,
    const syncer::SyncError& error) {
  failed_data_types_info_[error.model_type()] = error;
  LOG(ERROR) << "Failed to associate models for "
             << syncer::ModelTypeToString(error.model_type());
  UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed",
                            ModelTypeToHistogramInt(error.model_type()),
                            syncer::MODEL_TYPE_COUNT);
}

void ModelAssociationManager::TypeStartCallback(
    DataTypeController::StartResult start_result,
    const syncer::SyncMergeResult& local_merge_result,
    const syncer::SyncMergeResult& syncer_merge_result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation",
                         currently_associating_,
                         "DataType",
                         ModelTypeToString(currently_associating_->type()));

  DVLOG(1) << "ModelAssociationManager: TypeStartCallback";
  if (state_ == ABORTED) {
    // Now that we have finished with the current type we can stop
    // if abort was called.
    DVLOG(1) << "ModelAssociationManager: Doing an early return"
             << " because of abort";
    state_ = IDLE;
    return;
  }

  DCHECK(state_ == CONFIGURING);

  // We are done with this type. Clear it.
  DataTypeController* started_dtc = currently_associating_;
  currently_associating_ = NULL;

  if (start_result == DataTypeController::ASSOCIATION_FAILED) {
    DVLOG(1) << "ModelAssociationManager: Encountered a failed type";
    AppendToFailedDatatypesAndLogError(start_result,
                                       local_merge_result.error());
  } else if (start_result == DataTypeController::NEEDS_CRYPTO) {
    DVLOG(1) << "ModelAssociationManager: Encountered an undecryptable type";
    needs_crypto_types_.Put(started_dtc->type());
  }

  // Track the merge results if we succeeded or an association failure
  // occurred.
  if ((DataTypeController::IsSuccessfulResult(start_result) ||
       start_result == DataTypeController::ASSOCIATION_FAILED) &&
      syncer::ProtocolTypes().Has(local_merge_result.model_type())) {
    base::TimeDelta association_wait_time =
        current_type_association_start_time_ - association_start_time_;
    base::TimeDelta association_time =
        base::Time::Now() - current_type_association_start_time_;
    syncer::DataTypeAssociationStats stats =
        BuildAssociationStatsFromMergeResults(local_merge_result,
                                              syncer_merge_result,
                                              association_wait_time,
                                              association_time);
    result_processor_->OnSingleDataTypeAssociationDone(
        local_merge_result.model_type(), stats);
  }

  // If the type started normally, continue to the next type.
  // If the type is waiting for the cryptographer, continue to the next type.
  // Once the cryptographer is ready, we'll attempt to restart this type.
  // If this type encountered a type specific error continue to the next type.
  if (start_result == DataTypeController::NEEDS_CRYPTO ||
      DataTypeController::IsSuccessfulResult(start_result) ||
      start_result == DataTypeController::ASSOCIATION_FAILED) {

    DVLOG(1) << "ModelAssociationManager: type start callback returned "
             << start_result << " so calling LoadModelForNextType";
    LoadModelForNextType();
    return;
  }

  // Any other result requires reconfiguration. Pass it on through the callback.
  LOG(ERROR) << "Failed to configure " << started_dtc->name();
  DCHECK(local_merge_result.error().IsSet());
  DCHECK_EQ(started_dtc->type(), local_merge_result.error().model_type());
  DataTypeManager::ConfigureStatus configure_status =
      DataTypeManager::ABORTED;
  switch (start_result) {
    case DataTypeController::ABORTED:
      configure_status = DataTypeManager::ABORTED;
      break;
    case DataTypeController::UNRECOVERABLE_ERROR:
      configure_status = DataTypeManager::UNRECOVERABLE_ERROR;
      break;
    default:
      NOTREACHED();
      break;
  }

  std::map<syncer::ModelType, syncer::SyncError> errors;
  errors[local_merge_result.model_type()] = local_merge_result.error();

  // Put our state to idle.
  state_ = IDLE;

  DataTypeManager::ConfigureResult configure_result(configure_status,
                                                    associating_types_,
                                                    errors,
                                                    syncer::ModelTypeSet(),
                                                    needs_crypto_types_);
  result_processor_->OnModelAssociationDone(configure_result);
}

void ModelAssociationManager::LoadModelForNextType() {
  DVLOG(1) << "ModelAssociationManager: LoadModelForNextType";
  if (!needs_start_.empty()) {
    DVLOG(1) << "ModelAssociationManager: Starting " << needs_start_[0]->name();

    DataTypeController* dtc = needs_start_[0];
    needs_start_.erase(needs_start_.begin());
    // Move from |needs_start_| to |pending_model_load_|.
    pending_model_load_.insert(pending_model_load_.begin(), dtc);
    timer_.Start(FROM_HERE,
                 base::TimeDelta::FromSeconds(kDataTypeLoadWaitTimeInSeconds),
                 this,
                 &ModelAssociationManager::LoadModelForNextType);
    dtc->LoadModels(base::Bind(
        &ModelAssociationManager::ModelLoadCallback,
        weak_ptr_factory_.GetWeakPtr()));

    return;
  }

  DVLOG(1) << "ModelAssociationManager: All types have models loaded. "
          << "Moving on to StartAssociatingNextType.";

  // If all controllers have their |LoadModels| invoked then pass onto
  // |StartAssociatingNextType|.
  StartAssociatingNextType();
}

void ModelAssociationManager::ModelLoadCallback(
    syncer::ModelType type, syncer::SyncError error) {
  DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for "
          << syncer::ModelTypeToString(type);
  if (state_ == CONFIGURING) {
    DVLOG(1) << "ModelAssociationManager: ModelLoadCallback while configuring";
    for (std::vector<DataTypeController*>::iterator it =
             pending_model_load_.begin();
          it != pending_model_load_.end();
          ++it) {
      if ((*it)->type() == type) {
        // Each type is given |kDataTypeLoadWaitTimeInSeconds| time to load
        // (as controlled by the timer.). If the type does not load in that
        // time we move on to the next type. However if the type does
        // finish loading in that time we want to stop the timer. We stop
        // the timer, if the type that loaded is the same as the type that
        // we started the timer for(as indicated by the type on the head
        // of the list).
        // Note: Regardless of this timer value the associations will always
        // take place serially. The only thing this timer controls is how serial
        // the model load is. If this timer has a value of zero seconds then
        // the model loads will all be parallel.
        if (it == pending_model_load_.begin()) {
          DVLOG(1) << "ModelAssociationManager: Stopping timer";
          timer_.Stop();
        }
        DataTypeController* dtc = *it;
        pending_model_load_.erase(it);
        if (!error.IsSet()) {
          DVLOG(1) << "ModelAssociationManager:"
                  << " Calling StartAssociatingNextType";
          waiting_to_associate_.push_back(dtc);
          StartAssociatingNextType();
        } else {
          DVLOG(1) << "ModelAssociationManager: Encountered error loading";
          syncer::SyncMergeResult local_merge_result(type);
          local_merge_result.set_error(error);
          TypeStartCallback(DataTypeController::ASSOCIATION_FAILED,
                            local_merge_result,
                            syncer::SyncMergeResult(type));
       }
       return;
      }
    }
    NOTREACHED();
    return;
  } else if (state_ == IDLE) {
    DVLOG(1) << "ModelAssociationManager: Models loaded after configure cycle. "
            << "Informing DTM";
    // This datatype finished loading after the deadline imposed by the
    // originating configuration cycle. Inform the DataTypeManager that the
    // type has loaded, so that association may begin.
    result_processor_->OnTypesLoaded();
  } else {
    // If we're not IDLE or CONFIGURING, we're being invoked as part of an abort
    // process (possibly a reconfiguration, or disabling of a broken data type).
    DVLOG(1) << "ModelAssociationManager: ModelLoadCallback occurred while "
             << "not IDLE or CONFIGURING. Doing nothing.";
  }

}

void ModelAssociationManager::StartAssociatingNextType() {
  DCHECK_EQ(state_, CONFIGURING);
  DCHECK_EQ(currently_associating_, static_cast<DataTypeController*>(NULL));

  DVLOG(1) << "ModelAssociationManager: StartAssociatingNextType";
  if (!waiting_to_associate_.empty()) {
    DVLOG(1) << "ModelAssociationManager: Starting "
            << waiting_to_associate_[0]->name();
    DataTypeController* dtc = waiting_to_associate_[0];
    waiting_to_associate_.erase(waiting_to_associate_.begin());
    currently_associating_ = dtc;
    current_type_association_start_time_ = base::Time::Now();
    TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation",
                             currently_associating_,
                             "DataType",
                             ModelTypeToString(currently_associating_->type()));
    dtc->StartAssociating(base::Bind(
        &ModelAssociationManager::TypeStartCallback,
        weak_ptr_factory_.GetWeakPtr()));
    return;
  }

  // We are done with this cycle of association. Stop any failed types now.
  needs_stop_.clear();
  for (DataTypeController::TypeMap::const_iterator it = controllers_->begin();
       it != controllers_->end(); ++it) {
    DataTypeController* dtc = (*it).second.get();
    if (failed_data_types_info_.count(dtc->type()) > 0 &&
        dtc->state() != DataTypeController::NOT_RUNNING) {
      needs_stop_.push_back(dtc);
      DVLOG(1) << "ModelTypeToString: Will stop " << dtc->name();
    }
  }
  StopDisabledTypes();

  state_ = IDLE;

  DataTypeManager::ConfigureStatus configure_status = DataTypeManager::OK;

  if (!failed_data_types_info_.empty() ||
      !GetTypesWaitingToLoad().Empty() ||
      !needs_crypto_types_.Empty()) {
    // We have not configured all types that we have been asked to configure.
    // Either we have failed types or types that have not completed loading
    // yet.
    DVLOG(1) << "ModelAssociationManager: setting partial success";
    configure_status = DataTypeManager::PARTIAL_SUCCESS;
  }

  DataTypeManager::ConfigureResult result(configure_status,
                                          associating_types_,
                                          failed_data_types_info_,
                                          GetTypesWaitingToLoad(),
                                          needs_crypto_types_);
  result_processor_->OnModelAssociationDone(result);
  return;
}

syncer::ModelTypeSet ModelAssociationManager::GetTypesWaitingToLoad() {
  syncer::ModelTypeSet result;
  for (std::vector<DataTypeController*>::const_iterator it =
           pending_model_load_.begin();
       it != pending_model_load_.end();
       ++it) {
    result.Put((*it)->type());
  }
  return result;
}

base::OneShotTimer<ModelAssociationManager>*
    ModelAssociationManager::GetTimerForTesting() {
  return &timer_;
}

}  // namespace browser_sync
