// Copyright (c) 2010 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 "base/prefs/pref_change_registrar.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"

PrefChangeRegistrar::PrefChangeRegistrar() : service_(NULL) {}

PrefChangeRegistrar::~PrefChangeRegistrar() {
  // If you see an invalid memory access in this destructor, this
  // PrefChangeRegistrar might be subscribed to an OffTheRecordProfileImpl that
  // has been destroyed. This should not happen any more but be warned.
  // Feel free to contact battre@chromium.org in case this happens.
  RemoveAll();
}

void PrefChangeRegistrar::Init(PrefService* service) {
  DCHECK(IsEmpty() || service_ == service);
  service_ = service;
}

void PrefChangeRegistrar::Add(const char* path,
                              const base::Closure& obs) {
  Add(path, base::Bind(&PrefChangeRegistrar::InvokeUnnamedCallback, obs));
}

void PrefChangeRegistrar::Add(const char* path,
                              const NamedChangeCallback& obs) {
  if (!service_) {
    NOTREACHED();
    return;
  }
  DCHECK(!IsObserved(path)) << "Already had this pref registered.";

  service_->AddPrefObserver(path, this);
  observers_[path] = obs;
}

void PrefChangeRegistrar::Remove(const char* path) {
  DCHECK(IsObserved(path));

  observers_.erase(path);
  service_->RemovePrefObserver(path, this);
}

void PrefChangeRegistrar::RemoveAll() {
  for (ObserverMap::const_iterator it = observers_.begin();
       it != observers_.end(); ++it) {
    service_->RemovePrefObserver(it->first.c_str(), this);
  }

  observers_.clear();
}

bool PrefChangeRegistrar::IsEmpty() const {
  return observers_.empty();
}

bool PrefChangeRegistrar::IsObserved(const std::string& pref) {
  return observers_.find(pref) != observers_.end();
}

bool PrefChangeRegistrar::IsManaged() {
  for (ObserverMap::const_iterator it = observers_.begin();
       it != observers_.end(); ++it) {
    const PrefService::Preference* pref =
        service_->FindPreference(it->first.c_str());
    if (pref && pref->IsManaged())
      return true;
  }
  return false;
}

void PrefChangeRegistrar::OnPreferenceChanged(PrefService* service,
                                              const std::string& pref) {
  if (IsObserved(pref))
    observers_[pref].Run(pref);
}

void PrefChangeRegistrar::InvokeUnnamedCallback(const base::Closure& callback,
                                                const std::string& pref_name) {
  callback.Run();
}

PrefService* PrefChangeRegistrar::prefs() {
  return service_;
}

const PrefService* PrefChangeRegistrar::prefs() const {
  return service_;
}
