// Copyright (c) 2013 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 "ui/message_center/message_center_impl.h"

#include <algorithm>
#include <deque>
#include <memory>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/observer_list.h"
#include "base/stl_util.h"
#include "build/build_config.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/message_center_switches.h"
#include "ui/message_center/message_center_types.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_blocker.h"
#include "ui/message_center/notification_list.h"
#include "ui/message_center/notification_types.h"
#include "ui/message_center/popup_timers_controller.h"

namespace message_center {
namespace internal {

// ChangeQueue keeps track of all the changes that we need to make to the
// notification list once the visibility is set to VISIBILITY_TRANSIENT.
class ChangeQueue {
 public:
  enum ChangeType {
    CHANGE_TYPE_ADD = 0,
    CHANGE_TYPE_UPDATE,
    CHANGE_TYPE_DELETE
  };

  // Change represents an operation made on a notification.  Since it contains
  // the final state of the notification, we only keep the last change for a
  // particular notification that is in the notification list around.  There are
  // two ids; |id_| is the newest notification id that has been assigned by an
  // update, and |notification_list_id_| is the id of the notification it should
  // be updating as it exists in the notification list.
  class Change {
   public:
    Change(ChangeType type,
           const std::string& id,
           std::unique_ptr<Notification> notification);
    ~Change();

    // Used to transfer ownership of the contained notification.
    std::unique_ptr<Notification> PassNotification();

    Notification* notification() const { return notification_.get(); }
    // Returns the post-update ID. It means:
    // - ADD event: ID of the notification to be added.
    // - UPDATE event: ID of the notification after the change. If the change
    //   doesn't update its ID, this value is same as |notification_list_id|.
    // - DELETE event: ID of the notification to be deleted.
    const std::string& id() const { return id_; }
    ChangeType type() const { return type_; }
    bool by_user() const { return by_user_; }
    void set_by_user(bool by_user) { by_user_ = by_user; }
    // Returns the ID which is used in the notification list. In other word, it
    // means the ID before the change.
    const std::string& notification_list_id() const {
      return notification_list_id_;
    }
    void set_type(const ChangeType new_type) {
      type_ = new_type;
    }
    void ReplaceNotification(std::unique_ptr<Notification> new_notification);

   private:
    ChangeType type_;
    std::string id_;
    std::string notification_list_id_;
    bool by_user_;
    std::unique_ptr<Notification> notification_;

    DISALLOW_COPY_AND_ASSIGN(Change);
  };

  ChangeQueue();
  ~ChangeQueue();

  // Called when the message center has appropriate visibility.  Modifies
  // |message_center| but does not retain it.  This also causes the queue to
  // empty itself.
  void ApplyChanges(MessageCenterImpl* message_center);

  // Applies only the changes of the given ID.
  void ApplyChangesForId(MessageCenterImpl* message_center,
                         const std::string& id);

  // Causes a TYPE_ADD change to be added to the queue.
  void AddNotification(std::unique_ptr<Notification> notification);

  // Causes a TYPE_UPDATE change to be added to the queue.
  void UpdateNotification(const std::string& old_id,
                          std::unique_ptr<Notification> notification);

  // Causes a TYPE_DELETE change to be added to the queue.
  void EraseNotification(const std::string& id, bool by_user);

  // Returns whether the queue matches an id.  The id given will be matched
  // against the ID of all changes post-update, not the id of the notification
  // as it stands in the notification list.
  bool Has(const std::string& id) const;

  // Returns a Change that can be modified by the caller.  ChangeQueue retains
  // ownership of the Change; pointers should not be retained.
  Notification* GetLatestNotification(const std::string& id) const;

 private:
  void ApplyChangeInternal(MessageCenterImpl* message_center,
                           std::unique_ptr<Change> change);

  std::vector<std::unique_ptr<Change>> changes_;

  DISALLOW_COPY_AND_ASSIGN(ChangeQueue);
};

////////////////////////////////////////////////////////////////////////////////
// ChangeFinder

struct ChangeFinder {
  explicit ChangeFinder(const std::string& id) : id(id) {}
  bool operator()(const std::unique_ptr<ChangeQueue::Change>& change) {
    return change->id() == id;
  }

  std::string id;
};

////////////////////////////////////////////////////////////////////////////////
// ChangeQueue::Change

ChangeQueue::Change::Change(ChangeType type,
                            const std::string& id,
                            std::unique_ptr<Notification> notification)
    : type_(type),
      notification_list_id_(id),
      by_user_(false),
      notification_(std::move(notification)) {
  DCHECK(!id.empty());
  DCHECK(type != CHANGE_TYPE_DELETE || !notification_);

  id_ = notification_ ? notification_->id() : notification_list_id_;
}

ChangeQueue::Change::~Change() {}

std::unique_ptr<Notification> ChangeQueue::Change::PassNotification() {
  return std::move(notification_);
}

void ChangeQueue::Change::ReplaceNotification(
    std::unique_ptr<Notification> new_notification) {
  id_ = new_notification ? new_notification->id() : notification_list_id_;
  notification_.swap(new_notification);
}

////////////////////////////////////////////////////////////////////////////////
// ChangeQueue

ChangeQueue::ChangeQueue() {}

ChangeQueue::~ChangeQueue() {}

void ChangeQueue::ApplyChanges(MessageCenterImpl* message_center) {
  // This method is re-entrant.
  while (!changes_.empty()) {
    auto iter = changes_.begin();
    std::unique_ptr<Change> change(std::move(*iter));
    // TODO(dewittj): Replace changes_ with a deque.
    changes_.erase(iter);
    ApplyChangeInternal(message_center, std::move(change));
  }
}

void ChangeQueue::ApplyChangesForId(MessageCenterImpl* message_center,
                                    const std::string& id) {
  std::deque<Change*> changes_for_id;
  std::string interesting_id = id;

  // Traverses the queue in reverse so shat we can track changes which change
  // the notification's ID.
  auto iter = changes_.end();
  while (iter != changes_.begin()) {
    --iter;
    if (interesting_id != (*iter)->id())
      continue;
    std::unique_ptr<Change> change(std::move(*iter));

    interesting_id = change->notification_list_id();

    iter = changes_.erase(iter);
    changes_for_id.push_back(change.release());
  }

  while (!changes_for_id.empty()) {
    ApplyChangeInternal(message_center,
                        std::unique_ptr<Change>(changes_for_id.back()));
    changes_for_id.pop_back();
  }
}

void ChangeQueue::AddNotification(std::unique_ptr<Notification> notification) {
  std::string id = notification->id();
  changes_.push_back(
      base::MakeUnique<Change>(CHANGE_TYPE_ADD, id, std::move(notification)));
}

void ChangeQueue::UpdateNotification(
    const std::string& old_id,
    std::unique_ptr<Notification> notification) {
  auto iter =
      std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(old_id));
  if (iter == changes_.rend()) {
    changes_.push_back(base::MakeUnique<Change>(CHANGE_TYPE_UPDATE, old_id,
                                                std::move(notification)));
    return;
  }

  Change* change = iter->get();
  switch (change->type()) {
    case CHANGE_TYPE_ADD: {
      std::string id = notification->id();
      // Needs to add the change at the last, because if this change updates
      // its ID, some previous changes may affect new ID.
      // (eg. Add A, Update B->C, and This update A->B).
      changes_.erase(--(iter.base()));
      changes_.push_back(base::MakeUnique<Change>(CHANGE_TYPE_ADD, id,
                                                  std::move(notification)));
      break;
    }
    case CHANGE_TYPE_UPDATE:
      if (notification->id() == old_id) {
        // Safe to place the change at the previous place.
        change->ReplaceNotification(std::move(notification));
      } else if (change->id() == change->notification_list_id()) {
        std::string id = notification->id();
        // Safe to place the change at the last.
        changes_.erase(--(iter.base()));
        changes_.push_back(base::MakeUnique<Change>(CHANGE_TYPE_ADD, id,
                                                    std::move(notification)));
      } else {
        // Complex case: gives up to optimize.
        changes_.push_back(base::MakeUnique<Change>(CHANGE_TYPE_UPDATE, old_id,
                                                    std::move(notification)));
      }
      break;
    case CHANGE_TYPE_DELETE:
      // DELETE -> UPDATE. Something is wrong. Treats the UPDATE as ADD.
      changes_.push_back(base::MakeUnique<Change>(CHANGE_TYPE_ADD, old_id,
                                                  std::move(notification)));
      break;
    default:
      NOTREACHED();
  }
}

void ChangeQueue::EraseNotification(const std::string& id, bool by_user) {
  auto iter =
      std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(id));
  if (iter == changes_.rend()) {
    auto change = base::MakeUnique<Change>(CHANGE_TYPE_DELETE, id, nullptr);
    change->set_by_user(by_user);
    changes_.push_back(std::move(change));
    return;
  }

  Change* change = iter->get();
  switch (change->type()) {
    case CHANGE_TYPE_ADD:
      // ADD -> DELETE. Just removes both.
      changes_.erase(--(iter.base()));
      break;
    case CHANGE_TYPE_UPDATE:
      // UPDATE -> DELETE. Changes the previous UPDATE to DELETE.
      change->set_type(CHANGE_TYPE_DELETE);
      change->set_by_user(by_user);
      change->ReplaceNotification(nullptr);
      break;
    case CHANGE_TYPE_DELETE:
      // DELETE -> DELETE. Something is wrong. Combines them with overriding
      // the |by_user| flag.
      change->set_by_user(!change->by_user() && by_user);
      break;
    default:
      NOTREACHED();
  }
}

bool ChangeQueue::Has(const std::string& id) const {
  auto iter = std::find_if(changes_.begin(), changes_.end(), ChangeFinder(id));
  return iter != changes_.end();
}

Notification* ChangeQueue::GetLatestNotification(const std::string& id) const {
  auto iter = std::find_if(changes_.begin(), changes_.end(), ChangeFinder(id));
  if (iter == changes_.end())
    return NULL;

  return (*iter)->notification();
}

void ChangeQueue::ApplyChangeInternal(MessageCenterImpl* message_center,
                                      std::unique_ptr<Change> change) {
  switch (change->type()) {
    case CHANGE_TYPE_ADD:
      message_center->AddNotificationImmediately(change->PassNotification());
      break;
    case CHANGE_TYPE_UPDATE:
      message_center->UpdateNotificationImmediately(
          change->notification_list_id(), change->PassNotification());
      break;
    case CHANGE_TYPE_DELETE:
      message_center->RemoveNotificationImmediately(
          change->notification_list_id(), change->by_user());
      break;
    default:
      NOTREACHED();
  }
}

}  // namespace internal

////////////////////////////////////////////////////////////////////////////////
// MessageCenterImpl::NotificationCache

MessageCenterImpl::NotificationCache::NotificationCache()
    : unread_count(0) {}

MessageCenterImpl::NotificationCache::~NotificationCache() {}

void MessageCenterImpl::NotificationCache::Rebuild(
    const NotificationList::Notifications& notifications) {
  visible_notifications = notifications;
  RecountUnread();
}

void MessageCenterImpl::NotificationCache::RecountUnread() {
  unread_count = 0;
  for (auto* notification : visible_notifications) {
    if (!notification->IsRead())
      ++unread_count;
  }
}

////////////////////////////////////////////////////////////////////////////////
// MessageCenterImpl

MessageCenterImpl::MessageCenterImpl()
    : MessageCenter(),
      popup_timers_controller_(new PopupTimersController(this)),
      settings_provider_(NULL) {
  notification_list_.reset(new NotificationList(this));

  bool enable_message_center_changes_while_open = true;  // enable by default
  std::string arg = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
      switches::kMessageCenterChangesWhileOpen);
  if (!arg.empty()) {
    if (arg == "enabled")
      enable_message_center_changes_while_open = true;
    else if (arg == "disabled")
      enable_message_center_changes_while_open = false;
  }

  if (!enable_message_center_changes_while_open)
    notification_queue_.reset(new internal::ChangeQueue());
}

MessageCenterImpl::~MessageCenterImpl() {
  SetNotifierSettingsProvider(NULL);
}

void MessageCenterImpl::AddObserver(MessageCenterObserver* observer) {
  observer_list_.AddObserver(observer);
}

void MessageCenterImpl::RemoveObserver(MessageCenterObserver* observer) {
  observer_list_.RemoveObserver(observer);
}

void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker* blocker) {
  if (base::ContainsValue(blockers_, blocker))
    return;

  blocker->AddObserver(this);
  blockers_.push_back(blocker);
}

void MessageCenterImpl::RemoveNotificationBlocker(
    NotificationBlocker* blocker) {
  std::vector<NotificationBlocker*>::iterator iter =
      std::find(blockers_.begin(), blockers_.end(), blocker);
  if (iter == blockers_.end())
    return;
  blocker->RemoveObserver(this);
  blockers_.erase(iter);
}

void MessageCenterImpl::OnBlockingStateChanged(NotificationBlocker* blocker) {
  std::list<std::string> blocked_ids;
  NotificationList::PopupNotifications popups =
      notification_list_->GetPopupNotifications(blockers_, &blocked_ids);

  for (const auto& id : blocked_ids) {
    // Do not call MessageCenterImpl::MarkSinglePopupAsShown() directly here
    // just for performance reason. MessageCenterImpl::MarkSinglePopupAsShown()
    // calls NotificationList::MarkSinglePopupAsShown() and then updates the
    // unread count, but the whole cache will be recreated below.
    notification_list_->MarkSinglePopupAsShown(id, true);
  }
  notification_cache_.Rebuild(
      notification_list_->GetVisibleNotifications(blockers_));

  for (const auto& id : blocked_ids) {
    for (auto& observer : observer_list_)
      observer.OnNotificationUpdated(id);
  }
  for (auto& observer : observer_list_)
    observer.OnBlockingStateChanged(blocker);
}

void MessageCenterImpl::UpdateIconImage(
    const NotifierId& notifier_id, const gfx::Image& icon) {}

void MessageCenterImpl::NotifierGroupChanged() {}

void MessageCenterImpl::NotifierEnabledChanged(
    const NotifierId& notifier_id, bool enabled) {
  if (!enabled) {
    RemoveNotificationsForNotifierId(notifier_id);
  }
}

void MessageCenterImpl::SetVisibility(Visibility visibility) {
  visible_ = (visibility == VISIBILITY_MESSAGE_CENTER);

  if (visible_ && !locked_) {
    std::set<std::string> updated_ids;
    notification_list_->SetNotificationsShown(blockers_, &updated_ids);
    notification_cache_.RecountUnread();

    for (const auto& id : updated_ids) {
      for (auto& observer : observer_list_)
        observer.OnNotificationUpdated(id);
    }
  }

  if (notification_queue_ &&
      visibility == VISIBILITY_TRANSIENT) {
    notification_queue_->ApplyChanges(this);
  }

  for (auto& observer : observer_list_)
    observer.OnCenterVisibilityChanged(visibility);
}

bool MessageCenterImpl::IsMessageCenterVisible() const {
  return visible_;
}

size_t MessageCenterImpl::NotificationCount() const {
  return notification_cache_.visible_notifications.size();
}

size_t MessageCenterImpl::UnreadNotificationCount() const {
  return notification_cache_.unread_count;
}

bool MessageCenterImpl::HasPopupNotifications() const {
  return !IsMessageCenterVisible() &&
      notification_list_->HasPopupNotifications(blockers_);
}

bool MessageCenterImpl::IsQuietMode() const {
  return notification_list_->quiet_mode();
}

bool MessageCenterImpl::IsLockedState() const {
  return locked_;
}

bool MessageCenterImpl::HasClickedListener(const std::string& id) {
  scoped_refptr<NotificationDelegate> delegate =
      notification_list_->GetNotificationDelegate(id);
  return delegate.get() && delegate->HasClickedListener();
}

message_center::Notification* MessageCenterImpl::FindVisibleNotificationById(
    const std::string& id) {
  return notification_list_->GetNotificationById(id);
}

const NotificationList::Notifications&
MessageCenterImpl::GetVisibleNotifications() {
  return notification_cache_.visible_notifications;
}

NotificationList::PopupNotifications
    MessageCenterImpl::GetPopupNotifications() {
  return notification_list_->GetPopupNotifications(blockers_, NULL);
}

void MessageCenterImpl::ForceNotificationFlush(const std::string& id) {
  if (notification_queue_)
    notification_queue_->ApplyChangesForId(this, id);
}

//------------------------------------------------------------------------------
// Client code interface.
void MessageCenterImpl::AddNotification(
    std::unique_ptr<Notification> notification) {
  DCHECK(notification);
  const std::string id = notification->id();
  for (size_t i = 0; i < blockers_.size(); ++i)
    blockers_[i]->CheckState();

  if (notification_queue_ && visible_) {
    notification_queue_->AddNotification(std::move(notification));
    return;
  }

  AddNotificationImmediately(std::move(notification));
}

void MessageCenterImpl::AddNotificationImmediately(
    std::unique_ptr<Notification> notification) {
  const std::string id = notification->id();

  // Sometimes the notification can be added with the same id and the
  // |notification_list| will replace the notification instead of adding new.
  // This is essentially an update rather than addition.
  bool already_exists = (notification_list_->GetNotificationById(id) != NULL);
  notification_list_->AddNotification(std::move(notification));
  notification_cache_.Rebuild(
      notification_list_->GetVisibleNotifications(blockers_));

  if (already_exists) {
    for (auto& observer : observer_list_)
      observer.OnNotificationUpdated(id);
  } else {
    for (auto& observer : observer_list_)
      observer.OnNotificationAdded(id);
  }
}

void MessageCenterImpl::UpdateNotification(
    const std::string& old_id,
    std::unique_ptr<Notification> new_notification) {
  for (size_t i = 0; i < blockers_.size(); ++i)
    blockers_[i]->CheckState();

  if (notification_queue_ && visible_) {
    // We will allow notifications that are progress types (and stay progress
    // types) to be updated even if the message center is open.  There are 3
    // requirements here:
    //  * Notification of type PROGRESS exists with same ID in the center
    //  * There are no queued updates for this notification (they imply a change
    //    that violates the PROGRESS invariant
    //  * The new notification is type PROGRESS.
    // TODO(dewittj): Ensure this works when the ID is changed by the caller.
    // This shouldn't be an issue in practice since only W3C notifications
    // change the ID on update, and they don't have progress type notifications.
    bool update_keeps_progress_type =
        new_notification->type() == NOTIFICATION_TYPE_PROGRESS &&
        !notification_queue_->Has(old_id) &&
        notification_list_->HasNotificationOfType(old_id,
                                                  NOTIFICATION_TYPE_PROGRESS);
    if (!update_keeps_progress_type) {
      // Updates are allowed only for progress notifications.
      notification_queue_->UpdateNotification(old_id,
                                              std::move(new_notification));
      return;
    }
  }

  UpdateNotificationImmediately(old_id, std::move(new_notification));
}

void MessageCenterImpl::UpdateNotificationImmediately(
    const std::string& old_id,
    std::unique_ptr<Notification> new_notification) {
  std::string new_id = new_notification->id();
  notification_list_->UpdateNotificationMessage(old_id,
                                                std::move(new_notification));
  notification_cache_.Rebuild(
     notification_list_->GetVisibleNotifications(blockers_));
  if (old_id == new_id) {
    for (auto& observer : observer_list_)
      observer.OnNotificationUpdated(new_id);
  } else {
    for (auto& observer : observer_list_)
      observer.OnNotificationRemoved(old_id, false);
    for (auto& observer : observer_list_)
      observer.OnNotificationAdded(new_id);
  }
}

void MessageCenterImpl::RemoveNotification(const std::string& id,
                                           bool by_user) {
  if (notification_queue_ && !by_user && visible_) {
    notification_queue_->EraseNotification(id, by_user);
    return;
  }

  RemoveNotificationImmediately(id, by_user);
}

void MessageCenterImpl::RemoveNotificationImmediately(
    const std::string& id, bool by_user) {
  Notification* notification = FindVisibleNotificationById(id);
  if (notification == NULL)
    return;

  if (by_user && notification->pinned())
    return;

  // In many cases |id| is a reference to an existing notification instance
  // but the instance can be destructed in this method. Hence copies the id
  // explicitly here.
  std::string copied_id(id);

  scoped_refptr<NotificationDelegate> delegate =
      notification_list_->GetNotificationDelegate(copied_id);
  if (delegate.get())
    delegate->Close(by_user);

  notification_list_->RemoveNotification(copied_id);
  notification_cache_.Rebuild(
      notification_list_->GetVisibleNotifications(blockers_));
  for (auto& observer : observer_list_)
    observer.OnNotificationRemoved(copied_id, by_user);
}

void MessageCenterImpl::RemoveNotificationsForNotifierId(
    const NotifierId& notifier_id) {
  NotificationList::Notifications notifications =
      notification_list_->GetNotificationsByNotifierId(notifier_id);
  for (auto* notification : notifications)
    RemoveNotification(notification->id(), false);
  if (!notifications.empty()) {
    notification_cache_.Rebuild(
        notification_list_->GetVisibleNotifications(blockers_));
  }
}

void MessageCenterImpl::RemoveAllNotifications(bool by_user, RemoveType type) {
  bool remove_pinned = (type == RemoveType::ALL);

  const NotificationBlockers& blockers =
      remove_pinned ? NotificationBlockers() /* empty blockers */
                    : blockers_;             /* use default blockers */

  const NotificationList::Notifications notifications =
      notification_list_->GetVisibleNotifications(blockers);
  std::set<std::string> ids;
  for (auto* notification : notifications) {
    if (!remove_pinned && notification->pinned())
      continue;

    ids.insert(notification->id());
    scoped_refptr<NotificationDelegate> delegate = notification->delegate();
    if (delegate.get())
      delegate->Close(by_user);
    notification_list_->RemoveNotification(notification->id());
  }

  if (!ids.empty()) {
    notification_cache_.Rebuild(
        notification_list_->GetVisibleNotifications(blockers_));
  }
  for (const auto& id : ids) {
    for (auto& observer : observer_list_)
      observer.OnNotificationRemoved(id, by_user);
  }
}

void MessageCenterImpl::SetNotificationIcon(const std::string& notification_id,
                                            const gfx::Image& image) {
  bool updated = false;
  Notification* queue_notification =
      notification_queue_
          ? notification_queue_->GetLatestNotification(notification_id)
          : NULL;

  if (queue_notification) {
    queue_notification->set_icon(image);
    updated = true;
  } else {
    updated = notification_list_->SetNotificationIcon(notification_id, image);
  }

  if (updated) {
    for (auto& observer : observer_list_)
      observer.OnNotificationUpdated(notification_id);
  }
}

void MessageCenterImpl::SetNotificationImage(const std::string& notification_id,
                                             const gfx::Image& image) {
  bool updated = false;
  Notification* queue_notification =
      notification_queue_
          ? notification_queue_->GetLatestNotification(notification_id)
          : NULL;

  if (queue_notification) {
    queue_notification->set_image(image);
    updated = true;
  } else {
    updated = notification_list_->SetNotificationImage(notification_id, image);
  }

  if (updated) {
    for (auto& observer : observer_list_)
      observer.OnNotificationUpdated(notification_id);
  }
}

void MessageCenterImpl::SetNotificationButtonIcon(
    const std::string& notification_id, int button_index,
    const gfx::Image& image) {
  bool updated = false;
  Notification* queue_notification =
      notification_queue_
          ? notification_queue_->GetLatestNotification(notification_id)
          : NULL;

  if (queue_notification) {
    queue_notification->SetButtonIcon(button_index, image);
    updated = true;
  } else {
    updated = notification_list_->SetNotificationButtonIcon(
        notification_id, button_index, image);
  }

  if (updated) {
    for (auto& observer : observer_list_)
      observer.OnNotificationUpdated(notification_id);
  }
}

void MessageCenterImpl::DisableNotificationsByNotifier(
    const NotifierId& notifier_id) {
  if (settings_provider_) {
    // TODO(mukai): SetNotifierEnabled can just accept notifier_id?
    Notifier notifier(notifier_id, base::string16(), true);
    settings_provider_->SetNotifierEnabled(notifier, false);
    // The settings provider will call back to remove the notifications
    // belonging to the notifier id.
  } else {
    RemoveNotificationsForNotifierId(notifier_id);
  }
}

void MessageCenterImpl::ClickOnNotification(const std::string& id) {
  if (FindVisibleNotificationById(id) == NULL)
    return;
#if defined(OS_CHROMEOS)
  if (HasPopupNotifications())
    MarkSinglePopupAsShown(id, true);
#endif
  scoped_refptr<NotificationDelegate> delegate =
      notification_list_->GetNotificationDelegate(id);
  if (delegate.get())
    delegate->Click();
  for (auto& observer : observer_list_)
    observer.OnNotificationClicked(id);
}

void MessageCenterImpl::ClickOnNotificationButton(const std::string& id,
                                                  int button_index) {
  if (FindVisibleNotificationById(id) == NULL)
    return;
#if defined(OS_CHROMEOS)
  if (HasPopupNotifications())
    MarkSinglePopupAsShown(id, true);
#endif
  scoped_refptr<NotificationDelegate> delegate =
      notification_list_->GetNotificationDelegate(id);
  if (delegate.get())
    delegate->ButtonClick(button_index);
  for (auto& observer : observer_list_)
    observer.OnNotificationButtonClicked(id, button_index);
}

void MessageCenterImpl::ClickOnSettingsButton(const std::string& id) {
  scoped_refptr<NotificationDelegate> delegate =
      notification_list_->GetNotificationDelegate(id);
  if (delegate.get())
    delegate->SettingsClick();
  for (auto& observer : observer_list_)
    observer.OnNotificationSettingsClicked();
}

void MessageCenterImpl::MarkSinglePopupAsShown(const std::string& id,
                                               bool mark_notification_as_read) {
  if (FindVisibleNotificationById(id) == NULL)
    return;
#if !defined(OS_CHROMEOS)
  return this->RemoveNotification(id, false);
#else
  notification_list_->MarkSinglePopupAsShown(id, mark_notification_as_read);
  notification_cache_.RecountUnread();
  for (auto& observer : observer_list_)
    observer.OnNotificationUpdated(id);
#endif  // defined(OS_CHROMEOS)
}

void MessageCenterImpl::DisplayedNotification(
    const std::string& id,
    const DisplaySource source) {
  if (FindVisibleNotificationById(id) == NULL)
    return;

  if (HasPopupNotifications())
    notification_list_->MarkSinglePopupAsDisplayed(id);
  notification_cache_.RecountUnread();
  scoped_refptr<NotificationDelegate> delegate =
      notification_list_->GetNotificationDelegate(id);
  if (delegate.get())
    delegate->Display();
  for (auto& observer : observer_list_)
    observer.OnNotificationDisplayed(id, source);
}

void MessageCenterImpl::SetNotifierSettingsProvider(
    NotifierSettingsProvider* provider) {
  if (settings_provider_) {
    settings_provider_->RemoveObserver(this);
    settings_provider_ = NULL;
  }
  settings_provider_ = provider;
  if (settings_provider_)
    settings_provider_->AddObserver(this);
}

NotifierSettingsProvider* MessageCenterImpl::GetNotifierSettingsProvider() {
  return settings_provider_;
}

void MessageCenterImpl::SetQuietMode(bool in_quiet_mode) {
  if (in_quiet_mode != notification_list_->quiet_mode()) {
    notification_list_->SetQuietMode(in_quiet_mode);
    for (auto& observer : observer_list_)
      observer.OnQuietModeChanged(in_quiet_mode);
  }
  quiet_mode_timer_.reset();
}

void MessageCenterImpl::SetLockedState(bool locked) {
  if (locked != locked_) {
    locked_ = locked;
    for (auto& observer : observer_list_)
      observer.OnLockedStateChanged(locked);
  }
}

void MessageCenterImpl::EnterQuietModeWithExpire(
    const base::TimeDelta& expires_in) {
  if (quiet_mode_timer_) {
    // Note that the capital Reset() is the method to restart the timer, not
    // scoped_ptr::reset().
    quiet_mode_timer_->Reset();
  } else {
    notification_list_->SetQuietMode(true);
    for (auto& observer : observer_list_)
      observer.OnQuietModeChanged(true);

    quiet_mode_timer_.reset(new base::OneShotTimer);
    quiet_mode_timer_->Start(
        FROM_HERE,
        expires_in,
        base::Bind(
            &MessageCenterImpl::SetQuietMode, base::Unretained(this), false));
  }
}

void MessageCenterImpl::RestartPopupTimers() {
  if (popup_timers_controller_)
    popup_timers_controller_->StartAll();
}

void MessageCenterImpl::PausePopupTimers() {
  if (popup_timers_controller_)
    popup_timers_controller_->PauseAll();
}

void MessageCenterImpl::DisableTimersForTest() {
  popup_timers_controller_.reset();
}

void MessageCenterImpl::EnableChangeQueueForTest(bool enable) {
  if (enable)
    notification_queue_.reset(new internal::ChangeQueue());
  else
    notification_queue_.reset();
}

}  // namespace message_center
