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

#include <stddef.h>

#include "base/logging.h"
#include "components/prefs/pref_notifier.h"
#include "components/prefs/pref_observer.h"

PrefValueStore::PrefStoreKeeper::PrefStoreKeeper()
    : pref_value_store_(nullptr), type_(PrefValueStore::INVALID_STORE) {}

PrefValueStore::PrefStoreKeeper::~PrefStoreKeeper() {
  if (pref_store_.get()) {
    pref_store_->RemoveObserver(this);
    pref_store_ = nullptr;
  }
  pref_value_store_ = nullptr;
}

void PrefValueStore::PrefStoreKeeper::Initialize(
    PrefValueStore* store,
    PrefStore* pref_store,
    PrefValueStore::PrefStoreType type) {
  if (pref_store_.get()) {
    pref_store_->RemoveObserver(this);
    DCHECK(!pref_store_->HasObservers());
  }
  type_ = type;
  pref_value_store_ = store;
  pref_store_ = pref_store;
  if (pref_store_.get())
    pref_store_->AddObserver(this);
}

void PrefValueStore::PrefStoreKeeper::OnPrefValueChanged(
    const std::string& key) {
  pref_value_store_->OnPrefValueChanged(type_, key);
}

void PrefValueStore::PrefStoreKeeper::OnInitializationCompleted(
    bool succeeded) {
  pref_value_store_->OnInitializationCompleted(type_, succeeded);
}

PrefValueStore::PrefValueStore(PrefStore* managed_prefs,
                               PrefStore* supervised_user_prefs,
                               PrefStore* extension_prefs,
                               PrefStore* command_line_prefs,
                               PrefStore* user_prefs,
                               PrefStore* recommended_prefs,
                               PrefStore* default_prefs,
                               PrefNotifier* pref_notifier,
                               std::unique_ptr<Delegate> delegate)
    : pref_notifier_(pref_notifier),
      initialization_failed_(false),
      delegate_(std::move(delegate)) {
  InitPrefStore(MANAGED_STORE, managed_prefs);
  InitPrefStore(SUPERVISED_USER_STORE, supervised_user_prefs);
  InitPrefStore(EXTENSION_STORE, extension_prefs);
  InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
  InitPrefStore(USER_STORE, user_prefs);
  InitPrefStore(RECOMMENDED_STORE, recommended_prefs);
  InitPrefStore(DEFAULT_STORE, default_prefs);

  CheckInitializationCompleted();
  if (delegate_) {
    delegate_->Init(managed_prefs, supervised_user_prefs, extension_prefs,
                    command_line_prefs, user_prefs, recommended_prefs,
                    default_prefs, pref_notifier);
  }
}

PrefValueStore::~PrefValueStore() {}

std::unique_ptr<PrefValueStore> PrefValueStore::CloneAndSpecialize(
    PrefStore* managed_prefs,
    PrefStore* supervised_user_prefs,
    PrefStore* extension_prefs,
    PrefStore* command_line_prefs,
    PrefStore* user_prefs,
    PrefStore* recommended_prefs,
    PrefStore* default_prefs,
    PrefNotifier* pref_notifier,
    std::unique_ptr<Delegate> delegate) {
  DCHECK(pref_notifier);
  if (!managed_prefs)
    managed_prefs = GetPrefStore(MANAGED_STORE);
  if (!supervised_user_prefs)
    supervised_user_prefs = GetPrefStore(SUPERVISED_USER_STORE);
  if (!extension_prefs)
    extension_prefs = GetPrefStore(EXTENSION_STORE);
  if (!command_line_prefs)
    command_line_prefs = GetPrefStore(COMMAND_LINE_STORE);
  if (!user_prefs)
    user_prefs = GetPrefStore(USER_STORE);
  if (!recommended_prefs)
    recommended_prefs = GetPrefStore(RECOMMENDED_STORE);
  if (!default_prefs)
    default_prefs = GetPrefStore(DEFAULT_STORE);

  return std::make_unique<PrefValueStore>(
      managed_prefs, supervised_user_prefs, extension_prefs, command_line_prefs,
      user_prefs, recommended_prefs, default_prefs, pref_notifier,
      std::move(delegate));
}

void PrefValueStore::set_callback(const PrefChangedCallback& callback) {
  pref_changed_callback_ = callback;
}

bool PrefValueStore::GetValue(const std::string& name,
                              base::Value::Type type,
                              const base::Value** out_value) const {
  // Check the |PrefStore|s in order of their priority from highest to lowest,
  // looking for the first preference value with the given |name| and |type|.
  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    if (GetValueFromStoreWithType(name, type, static_cast<PrefStoreType>(i),
                                  out_value))
      return true;
  }
  return false;
}

bool PrefValueStore::GetRecommendedValue(const std::string& name,
                                         base::Value::Type type,
                                         const base::Value** out_value) const {
  return GetValueFromStoreWithType(name, type, RECOMMENDED_STORE, out_value);
}

void PrefValueStore::NotifyPrefChanged(
    const std::string& path,
    PrefValueStore::PrefStoreType new_store) {
  DCHECK(new_store != INVALID_STORE);
  // A notification is sent when the pref value in any store changes. If this
  // store is currently being overridden by a higher-priority store, the
  // effective value of the pref will not have changed.
  pref_notifier_->OnPreferenceChanged(path);
  if (!pref_changed_callback_.is_null())
    pref_changed_callback_.Run(path);
}

bool PrefValueStore::PrefValueInManagedStore(const std::string& name) const {
  return PrefValueInStore(name, MANAGED_STORE);
}

bool PrefValueStore::PrefValueInSupervisedStore(const std::string& name) const {
  return PrefValueInStore(name, SUPERVISED_USER_STORE);
}

bool PrefValueStore::PrefValueInExtensionStore(const std::string& name) const {
  return PrefValueInStore(name, EXTENSION_STORE);
}

bool PrefValueStore::PrefValueInUserStore(const std::string& name) const {
  return PrefValueInStore(name, USER_STORE);
}

bool PrefValueStore::PrefValueFromExtensionStore(
    const std::string& name) const {
  return ControllingPrefStoreForPref(name) == EXTENSION_STORE;
}

bool PrefValueStore::PrefValueFromUserStore(const std::string& name) const {
  return ControllingPrefStoreForPref(name) == USER_STORE;
}

bool PrefValueStore::PrefValueFromRecommendedStore(
    const std::string& name) const {
  return ControllingPrefStoreForPref(name) == RECOMMENDED_STORE;
}

bool PrefValueStore::PrefValueFromDefaultStore(const std::string& name) const {
  return ControllingPrefStoreForPref(name) == DEFAULT_STORE;
}

bool PrefValueStore::PrefValueUserModifiable(const std::string& name) const {
  PrefStoreType effective_store = ControllingPrefStoreForPref(name);
  return effective_store >= USER_STORE ||
         effective_store == INVALID_STORE;
}

bool PrefValueStore::PrefValueExtensionModifiable(
    const std::string& name) const {
  PrefStoreType effective_store = ControllingPrefStoreForPref(name);
  return effective_store >= EXTENSION_STORE ||
         effective_store == INVALID_STORE;
}

void PrefValueStore::UpdateCommandLinePrefStore(PrefStore* command_line_prefs) {
  InitPrefStore(COMMAND_LINE_STORE, command_line_prefs);
  if (delegate_)
    delegate_->UpdateCommandLinePrefStore(command_line_prefs);
}

bool PrefValueStore::IsInitializationComplete() const {
  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    const PrefStore* pref_store = GetPrefStore(static_cast<PrefStoreType>(i));
    if (pref_store && !pref_store->IsInitializationComplete())
      return false;
  }
  return true;
}

bool PrefValueStore::PrefValueInStore(
    const std::string& name,
    PrefValueStore::PrefStoreType store) const {
  // Declare a temp Value* and call GetValueFromStore,
  // ignoring the output value.
  const base::Value* tmp_value = nullptr;
  return GetValueFromStore(name, store, &tmp_value);
}

bool PrefValueStore::PrefValueInStoreRange(
    const std::string& name,
    PrefValueStore::PrefStoreType first_checked_store,
    PrefValueStore::PrefStoreType last_checked_store) const {
  if (first_checked_store > last_checked_store) {
    NOTREACHED();
    return false;
  }

  for (size_t i = first_checked_store;
       i <= static_cast<size_t>(last_checked_store); ++i) {
    if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
      return true;
  }
  return false;
}

PrefValueStore::PrefStoreType PrefValueStore::ControllingPrefStoreForPref(
    const std::string& name) const {
  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    if (PrefValueInStore(name, static_cast<PrefStoreType>(i)))
      return static_cast<PrefStoreType>(i);
  }
  return INVALID_STORE;
}

bool PrefValueStore::GetValueFromStore(const std::string& name,
                                       PrefValueStore::PrefStoreType store_type,
                                       const base::Value** out_value) const {
  // Only return true if we find a value and it is the correct type, so stale
  // values with the incorrect type will be ignored.
  const PrefStore* store = GetPrefStore(static_cast<PrefStoreType>(store_type));
  if (store && store->GetValue(name, out_value))
    return true;

  // No valid value found for the given preference name: set the return value
  // to false.
  *out_value = nullptr;
  return false;
}

bool PrefValueStore::GetValueFromStoreWithType(
    const std::string& name,
    base::Value::Type type,
    PrefStoreType store,
    const base::Value** out_value) const {
  if (GetValueFromStore(name, store, out_value)) {
    if ((*out_value)->type() == type)
      return true;

    LOG(WARNING) << "Expected type for " << name << " is " << type
                 << " but got " << (*out_value)->type() << " in store "
                 << store;
  }

  *out_value = nullptr;
  return false;
}

void PrefValueStore::OnPrefValueChanged(PrefValueStore::PrefStoreType type,
                                        const std::string& key) {
  NotifyPrefChanged(key, type);
}

void PrefValueStore::OnInitializationCompleted(
    PrefValueStore::PrefStoreType type, bool succeeded) {
  if (initialization_failed_)
    return;
  if (!succeeded) {
    initialization_failed_ = true;
    pref_notifier_->OnInitializationCompleted(false);
    return;
  }
  CheckInitializationCompleted();
}

void PrefValueStore::InitPrefStore(PrefValueStore::PrefStoreType type,
                                   PrefStore* pref_store) {
  pref_stores_[type].Initialize(this, pref_store, type);
}

void PrefValueStore::CheckInitializationCompleted() {
  if (initialization_failed_)
    return;
  for (size_t i = 0; i <= PREF_STORE_TYPE_MAX; ++i) {
    scoped_refptr<PrefStore> store =
        GetPrefStore(static_cast<PrefStoreType>(i));
    if (store.get() && !store->IsInitializationComplete())
      return;
  }
  pref_notifier_->OnInitializationCompleted(true);
}
