// 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_) {
    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_) {
    pref_store_->RemoveObserver(this);
    DCHECK(!pref_store_->HasObservers());
  }
  type_ = type;
  pref_value_store_ = store;
  pref_store_ = pref_store;
  if (pref_store_)
    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::HasPrefStore(PrefStoreType type) const {
  return GetPrefStore(type);
}

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);
}
