// 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 "ui/message_center/notification_list.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "ui/gfx/image/image.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/notification_blocker.h"
#include "ui/message_center/notification_types.h"

namespace message_center {

namespace {

bool ShouldShowNotificationAsPopup(
    const Notification& notification,
    const NotificationBlockers& blockers) {
  for (size_t i = 0; i < blockers.size(); ++i) {
    if (!blockers[i]->ShouldShowNotificationAsPopup(notification.notifier_id()))
      return false;
  }
  return true;
}

}  // namespace

bool ComparePriorityTimestampSerial::operator()(Notification* n1,
                                                Notification* n2) {
  if (n1->priority() > n2->priority())  // Higher pri go first.
    return true;
  if (n1->priority() < n2->priority())
    return false;
  return CompareTimestampSerial()(n1, n2);
}

bool CompareTimestampSerial::operator()(Notification* n1, Notification* n2) {
  if (n1->timestamp() > n2->timestamp())  // Newer come first.
    return true;
  if (n1->timestamp() < n2->timestamp())
    return false;
  if (n1->serial_number() > n2->serial_number())  // Newer come first.
    return true;
  if (n1->serial_number() < n2->serial_number())
    return false;
  return false;
}

NotificationList::NotificationList()
    : message_center_visible_(false),
      quiet_mode_(false) {
}

NotificationList::~NotificationList() {
  STLDeleteContainerPointers(notifications_.begin(), notifications_.end());
}

void NotificationList::SetMessageCenterVisible(
    bool visible,
    std::set<std::string>* updated_ids) {
  if (message_center_visible_ == visible)
    return;

  message_center_visible_ = visible;

  if (!visible)
    return;

  for (Notifications::iterator iter = notifications_.begin();
       iter != notifications_.end(); ++iter) {
    Notification* notification = *iter;
    bool was_popup = notification->shown_as_popup();
    bool was_read = notification->IsRead();
    if (notification->priority() < SYSTEM_PRIORITY)
      notification->set_shown_as_popup(true);
    notification->set_is_read(true);
    if (updated_ids && !(was_popup && was_read))
      updated_ids->insert(notification->id());
  }
}

void NotificationList::AddNotification(scoped_ptr<Notification> notification) {
  PushNotification(notification.Pass());
}

void NotificationList::UpdateNotificationMessage(
    const std::string& old_id,
    scoped_ptr<Notification> new_notification) {
  Notifications::iterator iter = GetNotification(old_id);
  if (iter == notifications_.end())
    return;

  new_notification->CopyState(*iter);

  // Handles priority promotion. If the notification is already dismissed but
  // the updated notification has higher priority, it should re-appear as a
  // toast. Notifications coming from websites through the Web Notification API
  // will always re-appear on update.
  if ((*iter)->priority() < new_notification->priority() ||
      new_notification->notifier_id().type == NotifierId::WEB_PAGE) {
    new_notification->set_is_read(false);
    new_notification->set_shown_as_popup(false);
  }

  // Do not use EraseNotification and PushNotification, since we don't want to
  // change unread counts nor to update is_read/shown_as_popup states.
  Notification* old = *iter;
  notifications_.erase(iter);
  delete old;

  // We really don't want duplicate IDs.
  DCHECK(GetNotification(new_notification->id()) == notifications_.end());
  notifications_.insert(new_notification.release());
}

void NotificationList::RemoveNotification(const std::string& id) {
  EraseNotification(GetNotification(id));
}

NotificationList::Notifications NotificationList::GetNotificationsByNotifierId(
        const NotifierId& notifier_id) {
  Notifications notifications;
  for (Notifications::iterator iter = notifications_.begin();
       iter != notifications_.end(); ++iter) {
    if ((*iter)->notifier_id() == notifier_id)
      notifications.insert(*iter);
  }
  return notifications;
}

bool NotificationList::SetNotificationIcon(const std::string& notification_id,
                                           const gfx::Image& image) {
  Notifications::iterator iter = GetNotification(notification_id);
  if (iter == notifications_.end())
    return false;
  (*iter)->set_icon(image);
  return true;
}

bool NotificationList::SetNotificationImage(const std::string& notification_id,
                                            const gfx::Image& image) {
  Notifications::iterator iter = GetNotification(notification_id);
  if (iter == notifications_.end())
    return false;
  (*iter)->set_image(image);
  return true;
}

bool NotificationList::SetNotificationButtonIcon(
    const std::string& notification_id, int button_index,
    const gfx::Image& image) {
  Notifications::iterator iter = GetNotification(notification_id);
  if (iter == notifications_.end())
    return false;
  (*iter)->SetButtonIcon(button_index, image);
  return true;
}

bool NotificationList::HasNotificationOfType(const std::string& id,
                                             const NotificationType type) {
  Notifications::iterator iter = GetNotification(id);
  if (iter == notifications_.end())
    return false;

  return (*iter)->type() == type;
}

bool NotificationList::HasPopupNotifications(
    const NotificationBlockers& blockers) {
  for (Notifications::iterator iter = notifications_.begin();
       iter != notifications_.end(); ++iter) {
    if ((*iter)->priority() < DEFAULT_PRIORITY)
      break;
    if (!ShouldShowNotificationAsPopup(**iter, blockers))
      continue;
    if (!(*iter)->shown_as_popup())
      return true;
  }
  return false;
}

NotificationList::PopupNotifications NotificationList::GetPopupNotifications(
    const NotificationBlockers& blockers,
    std::list<std::string>* blocked_ids) {
  PopupNotifications result;
  size_t default_priority_popup_count = 0;

  // Collect notifications that should be shown as popups. Start from oldest.
  for (Notifications::const_reverse_iterator iter = notifications_.rbegin();
       iter != notifications_.rend(); iter++) {
    if ((*iter)->shown_as_popup())
      continue;

    // No popups for LOW/MIN priority.
    if ((*iter)->priority() < DEFAULT_PRIORITY)
      continue;

    if (!ShouldShowNotificationAsPopup(**iter, blockers)) {
      if (blocked_ids)
        blocked_ids->push_back((*iter)->id());
      continue;
    }

    // Checking limits. No limits for HIGH/MAX priority. DEFAULT priority
    // will return at most kMaxVisiblePopupNotifications entries. If the
    // popup entries are more, older entries are used. see crbug.com/165768
    if ((*iter)->priority() == DEFAULT_PRIORITY &&
        default_priority_popup_count++ >= kMaxVisiblePopupNotifications) {
      continue;
    }

    result.insert(*iter);
  }
  return result;
}

void NotificationList::MarkSinglePopupAsShown(
    const std::string& id, bool mark_notification_as_read) {
  Notifications::iterator iter = GetNotification(id);
  DCHECK(iter != notifications_.end());

  if ((*iter)->shown_as_popup())
    return;

  // System notification is marked as shown only when marked as read.
  if ((*iter)->priority() != SYSTEM_PRIORITY || mark_notification_as_read)
    (*iter)->set_shown_as_popup(true);

  // The popup notification is already marked as read when it's displayed.
  // Set the is_read() back to false if necessary.
  if (!mark_notification_as_read)
    (*iter)->set_is_read(false);
}

void NotificationList::MarkSinglePopupAsDisplayed(const std::string& id) {
  Notifications::iterator iter = GetNotification(id);
  if (iter == notifications_.end())
    return;

  if ((*iter)->shown_as_popup())
    return;

  if (!(*iter)->IsRead())
    (*iter)->set_is_read(true);
}

NotificationDelegate* NotificationList::GetNotificationDelegate(
    const std::string& id) {
  Notifications::iterator iter = GetNotification(id);
  if (iter == notifications_.end())
    return NULL;
  return (*iter)->delegate();
}

void NotificationList::SetQuietMode(bool quiet_mode) {
  quiet_mode_ = quiet_mode;
  if (quiet_mode_) {
    for (Notifications::iterator iter = notifications_.begin();
         iter != notifications_.end();
         ++iter) {
      (*iter)->set_shown_as_popup(true);
    }
  }
}

Notification* NotificationList::GetNotificationById(const std::string& id) {
  Notifications::iterator iter = GetNotification(id);
  if (iter != notifications_.end())
    return *iter;
  return NULL;
}

NotificationList::Notifications NotificationList::GetVisibleNotifications(
    const NotificationBlockers& blockers) const {
  Notifications result;
  for (Notifications::const_iterator iter = notifications_.begin();
       iter != notifications_.end(); ++iter) {
    bool should_show = true;
    for (size_t i = 0; i < blockers.size(); ++i) {
      if (!blockers[i]->ShouldShowNotification((*iter)->notifier_id())) {
        should_show = false;
        break;
      }
    }
    if (should_show)
      result.insert(*iter);
  }

  return result;
}

size_t NotificationList::NotificationCount(
    const NotificationBlockers& blockers) const {
  return GetVisibleNotifications(blockers).size();
}

size_t NotificationList::UnreadCount(
    const NotificationBlockers& blockers) const {
  Notifications notifications = GetVisibleNotifications(blockers);
  size_t unread_count = 0;
  for (Notifications::const_iterator iter = notifications.begin();
       iter != notifications.end(); ++iter) {
    if (!(*iter)->IsRead())
      ++unread_count;
  }
  return unread_count;
}

NotificationList::Notifications::iterator NotificationList::GetNotification(
    const std::string& id) {
  for (Notifications::iterator iter = notifications_.begin();
       iter != notifications_.end(); ++iter) {
    if ((*iter)->id() == id)
      return iter;
  }
  return notifications_.end();
}

void NotificationList::EraseNotification(Notifications::iterator iter) {
  delete *iter;
  notifications_.erase(iter);
}

void NotificationList::PushNotification(scoped_ptr<Notification> notification) {
  // Ensure that notification.id is unique by erasing any existing
  // notification with the same id (shouldn't normally happen).
  Notifications::iterator iter = GetNotification(notification->id());
  bool state_inherited = false;
  if (iter != notifications_.end()) {
    notification->CopyState(*iter);
    state_inherited = true;
    EraseNotification(iter);
  }
  // Add the notification to the the list and mark it unread and unshown.
  if (!state_inherited) {
    // TODO(mukai): needs to distinguish if a notification is dismissed by
    // the quiet mode or user operation.
    notification->set_is_read(false);
    notification->set_shown_as_popup(message_center_visible_
                                     || quiet_mode_
                                     || notification->shown_as_popup());
  }
  // Take ownership. The notification can only be removed from the list
  // in EraseNotification(), which will delete it.
  notifications_.insert(notification.release());
}

}  // namespace message_center
