// 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 "components/sync_preferences/pref_service_syncable.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/strings/string_number_conversions.h"
#include "base/value_conversions.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/default_pref_store.h"
#include "components/prefs/overlay_user_pref_store.h"
#include "components/prefs/pref_notifier_impl.h"
#include "components/prefs/pref_registry.h"
#include "components/prefs/pref_value_store.h"
#include "components/sync_preferences/pref_model_associator.h"
#include "components/sync_preferences/pref_service_syncable_observer.h"

namespace sync_preferences {

PrefServiceSyncable::PrefServiceSyncable(
    PrefNotifierImpl* pref_notifier,
    PrefValueStore* pref_value_store,
    PersistentPrefStore* user_prefs,
    user_prefs::PrefRegistrySyncable* pref_registry,
    const PrefModelAssociatorClient* pref_model_associator_client,
    base::Callback<void(PersistentPrefStore::PrefReadError)>
        read_error_callback,
    bool async)
    : PrefService(pref_notifier,
                  pref_value_store,
                  user_prefs,
                  pref_registry,
                  read_error_callback,
                  async),
      pref_service_forked_(false),
      pref_sync_associator_(pref_model_associator_client, syncer::PREFERENCES),
      priority_pref_sync_associator_(pref_model_associator_client,
                                     syncer::PRIORITY_PREFERENCES) {
  pref_sync_associator_.SetPrefService(this);
  priority_pref_sync_associator_.SetPrefService(this);

  // Let PrefModelAssociators know about changes to preference values.
  pref_value_store->set_callback(base::Bind(
      &PrefServiceSyncable::ProcessPrefChange, base::Unretained(this)));

  // Add already-registered syncable preferences to PrefModelAssociator.
  for (PrefRegistry::const_iterator it = pref_registry->begin();
       it != pref_registry->end(); ++it) {
    const std::string& path = it->first;
    AddRegisteredSyncablePreference(path,
                                    pref_registry_->GetRegistrationFlags(path));
  }

  // Watch for syncable preferences registered after this point.
  pref_registry->SetSyncableRegistrationCallback(
      base::Bind(&PrefServiceSyncable::AddRegisteredSyncablePreference,
                 base::Unretained(this)));
}

PrefServiceSyncable::~PrefServiceSyncable() {
  // Remove our callback from the registry, since it may outlive us.
  user_prefs::PrefRegistrySyncable* registry =
      static_cast<user_prefs::PrefRegistrySyncable*>(pref_registry_.get());
  registry->SetSyncableRegistrationCallback(
      user_prefs::PrefRegistrySyncable::SyncableRegistrationCallback());
}

PrefServiceSyncable* PrefServiceSyncable::CreateIncognitoPrefService(
    PrefStore* incognito_extension_pref_store,
    const std::vector<const char*>& overlay_pref_names) {
  pref_service_forked_ = true;
  PrefNotifierImpl* pref_notifier = new PrefNotifierImpl();
  OverlayUserPrefStore* incognito_pref_store =
      new OverlayUserPrefStore(user_pref_store_.get());
  for (const char* overlay_pref_name : overlay_pref_names)
    incognito_pref_store->RegisterOverlayPref(overlay_pref_name);

  scoped_refptr<user_prefs::PrefRegistrySyncable> forked_registry =
      static_cast<user_prefs::PrefRegistrySyncable*>(pref_registry_.get())
          ->ForkForIncognito();
  PrefServiceSyncable* incognito_service = new PrefServiceSyncable(
      pref_notifier,
      pref_value_store_->CloneAndSpecialize(NULL,  // managed
                                            NULL,  // supervised_user
                                            incognito_extension_pref_store,
                                            NULL,  // command_line_prefs
                                            incognito_pref_store,
                                            NULL,  // recommended
                                            forked_registry->defaults().get(),
                                            pref_notifier),
      incognito_pref_store, forked_registry.get(),
      pref_sync_associator_.client(), read_error_callback_, false);
  return incognito_service;
}

bool PrefServiceSyncable::IsSyncing() {
  return pref_sync_associator_.models_associated();
}

bool PrefServiceSyncable::IsPrioritySyncing() {
  return priority_pref_sync_associator_.models_associated();
}

bool PrefServiceSyncable::IsPrefSynced(const std::string& name) const {
  return pref_sync_associator_.IsPrefSynced(name) ||
         priority_pref_sync_associator_.IsPrefSynced(name);
}

void PrefServiceSyncable::AddObserver(PrefServiceSyncableObserver* observer) {
  observer_list_.AddObserver(observer);
}

void PrefServiceSyncable::RemoveObserver(
    PrefServiceSyncableObserver* observer) {
  observer_list_.RemoveObserver(observer);
}

syncer::SyncableService* PrefServiceSyncable::GetSyncableService(
    const syncer::ModelType& type) {
  if (type == syncer::PREFERENCES) {
    return &pref_sync_associator_;
  } else if (type == syncer::PRIORITY_PREFERENCES) {
    return &priority_pref_sync_associator_;
  } else {
    NOTREACHED() << "invalid model type: " << type;
    return NULL;
  }
}

void PrefServiceSyncable::UpdateCommandLinePrefStore(
    PrefStore* cmd_line_store) {
  // If |pref_service_forked_| is true, then this PrefService and the forked
  // copies will be out of sync.
  DCHECK(!pref_service_forked_);
  PrefService::UpdateCommandLinePrefStore(cmd_line_store);
}

void PrefServiceSyncable::AddSyncedPrefObserver(const std::string& name,
                                                SyncedPrefObserver* observer) {
  pref_sync_associator_.AddSyncedPrefObserver(name, observer);
  priority_pref_sync_associator_.AddSyncedPrefObserver(name, observer);
}

void PrefServiceSyncable::RemoveSyncedPrefObserver(
    const std::string& name,
    SyncedPrefObserver* observer) {
  pref_sync_associator_.RemoveSyncedPrefObserver(name, observer);
  priority_pref_sync_associator_.RemoveSyncedPrefObserver(name, observer);
}

void PrefServiceSyncable::RegisterMergeDataFinishedCallback(
    const base::Closure& callback) {
  pref_sync_associator_.RegisterMergeDataFinishedCallback(callback);
}

// Set the PrefModelAssociatorClient to use for that object during tests.
void PrefServiceSyncable::SetPrefModelAssociatorClientForTesting(
    const PrefModelAssociatorClient* pref_model_associator_client) {
  pref_sync_associator_.SetPrefModelAssociatorClientForTesting(
      pref_model_associator_client);
  priority_pref_sync_associator_.SetPrefModelAssociatorClientForTesting(
      pref_model_associator_client);
}

void PrefServiceSyncable::AddRegisteredSyncablePreference(
    const std::string& path,
    uint32_t flags) {
  DCHECK(FindPreference(path));
  if (flags & user_prefs::PrefRegistrySyncable::SYNCABLE_PREF) {
    pref_sync_associator_.RegisterPref(path.c_str());
  } else if (flags & user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF) {
    priority_pref_sync_associator_.RegisterPref(path.c_str());
  }
}

void PrefServiceSyncable::OnIsSyncingChanged() {
  for (auto& observer : observer_list_)
    observer.OnIsSyncingChanged();
}

void PrefServiceSyncable::ProcessPrefChange(const std::string& name) {
  pref_sync_associator_.ProcessPrefChange(name);
  priority_pref_sync_associator_.ProcessPrefChange(name);
}

}  // namespace sync_preferences
