// 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 "content/browser/notification_service_impl.h"

#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_types.h"

namespace  content {

namespace {

base::LazyInstance<base::ThreadLocalPointer<NotificationServiceImpl> >
    lazy_tls_ptr = LAZY_INSTANCE_INITIALIZER;

}  // namespace

// static
NotificationServiceImpl* NotificationServiceImpl::current() {
  return lazy_tls_ptr.Pointer()->Get();
}

// static
NotificationService* NotificationService::current() {
  return NotificationServiceImpl::current();
}

// static
NotificationService* NotificationService::Create() {
  return new NotificationServiceImpl;
}

// static
bool NotificationServiceImpl::HasKey(const NotificationSourceMap& map,
                                     const NotificationSource& source) {
  return map.find(source.map_key()) != map.end();
}

NotificationServiceImpl::NotificationServiceImpl() {
  DCHECK(current() == NULL);
  lazy_tls_ptr.Pointer()->Set(this);
}

void NotificationServiceImpl::AddObserver(NotificationObserver* observer,
                                          int type,
                                          const NotificationSource& source) {
  // We have gotten some crashes where the observer pointer is NULL. The problem
  // is that this happens when we actually execute a notification, so have no
  // way of knowing who the bad observer was. We want to know when this happens
  // in release mode so we know what code to blame the crash on (since this is
  // guaranteed to crash later).
  CHECK(observer);

  NotificationObserverList* observer_list;
  if (HasKey(observers_[type], source)) {
    observer_list = observers_[type][source.map_key()];
  } else {
    observer_list = new NotificationObserverList;
    observers_[type][source.map_key()] = observer_list;
  }

  observer_list->AddObserver(observer);
#ifndef NDEBUG
  ++observer_counts_[type];
#endif
}

void NotificationServiceImpl::RemoveObserver(NotificationObserver* observer,
                                             int type,
                                             const NotificationSource& source) {
  // This is a very serious bug.  An object is most likely being deleted on
  // the wrong thread, and as a result another thread's NotificationServiceImpl
  // has its deleted pointer in its map.  A garbge object will be called in the
  // future.
  // NOTE: when this check shows crashes, use BrowserThread::DeleteOnIOThread or
  // other variants as the trait on the object.
  CHECK(HasKey(observers_[type], source));

  NotificationObserverList* observer_list =
      observers_[type][source.map_key()];
  if (observer_list) {
    observer_list->RemoveObserver(observer);
    if (!observer_list->might_have_observers()) {
      observers_[type].erase(source.map_key());
      delete observer_list;
    }
#ifndef NDEBUG
    --observer_counts_[type];
#endif
  }
}

void NotificationServiceImpl::Notify(int type,
                                     const NotificationSource& source,
                                     const NotificationDetails& details) {
  DCHECK_GT(type, NOTIFICATION_ALL) <<
      "Allowed for observing, but not posting.";

  // There's no particular reason for the order in which the different
  // classes of observers get notified here.

  // Notify observers of all types and all sources
  if (HasKey(observers_[NOTIFICATION_ALL], AllSources()) &&
      source != AllSources()) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[NOTIFICATION_ALL][AllSources().map_key()],
                      Observe(type, source, details));
  }

  // Notify observers of all types and the given source
  if (HasKey(observers_[NOTIFICATION_ALL], source)) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[NOTIFICATION_ALL][source.map_key()],
                      Observe(type, source, details));
  }

  // Notify observers of the given type and all sources
  if (HasKey(observers_[type], AllSources()) &&
      source != AllSources()) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[type][AllSources().map_key()],
                      Observe(type, source, details));
  }

  // Notify observers of the given type and the given source
  if (HasKey(observers_[type], source)) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[type][source.map_key()],
                      Observe(type, source, details));
  }
}


NotificationServiceImpl::~NotificationServiceImpl() {
  lazy_tls_ptr.Pointer()->Set(NULL);

#ifndef NDEBUG
  for (int i = 0; i < static_cast<int>(observer_counts_.size()); i++) {
    if (observer_counts_[i] > 0) {
      // This may not be completely fixable -- see
      // http://code.google.com/p/chromium/issues/detail?id=11010 .
      VLOG(1) << observer_counts_[i] << " notification observer(s) leaked "
                 "of notification type " << i;
    }
  }
#endif

  for (int i = 0; i < static_cast<int>(observers_.size()); i++) {
    NotificationSourceMap omap = observers_[i];
    for (NotificationSourceMap::iterator it = omap.begin();
         it != omap.end(); ++it)
      delete it->second;
  }
}

}  // namespace content
