// 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 <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "base/values.h"
#include "ui/gfx/image/image.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/notification_blocker.h"
#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/message_center/public/cpp/notification.h"
#include "ui/message_center/public/cpp/notification_types.h"

namespace message_center {

namespace {

bool ShouldShowNotificationAsPopup(
    const Notification& notification,
    const NotificationBlockers& blockers) {
  for (auto* blocker : blockers) {
    if (!blocker->ShouldShowNotificationAsPopup(notification))
      return false;
  }
  return true;
}

}  // namespace

bool ComparePriorityTimestampSerial::operator()(Notification* n1,
                                                Notification* n2) const {
  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) const {
  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;
}

bool NotificationList::NotificationState::operator!=(
    const NotificationState& other) const {
  return shown_as_popup != other.shown_as_popup || is_read != other.is_read;
}

NotificationList::NotificationList(MessageCenter* message_center)
    : message_center_(message_center),
      quiet_mode_(false) {
}

NotificationList::~NotificationList() {
}

void NotificationList::SetNotificationsShown(
    const NotificationBlockers& blockers,
    std::set<std::string>* updated_ids) {
  Notifications notifications = GetVisibleNotifications(blockers);

  for (Notification* notification : notifications) {
    NotificationState* state = &GetNotification(notification->id())->second;
    const NotificationState original_state = *state;
    if (notification->priority() < SYSTEM_PRIORITY)
      state->shown_as_popup = true;
    state->is_read = true;
    if (updated_ids && (original_state != *state))
      updated_ids->insert(notification->id());
  }
}

void NotificationList::AddNotification(
    std::unique_ptr<Notification> notification) {
  PushNotification(std::move(notification));
}

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

  NotificationState state = iter->second;

  if ((new_notification->renotify() ||
       !message_center_->HasMessageCenterView()) &&
      !quiet_mode_) {
    state = NotificationState();
  }

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

  // We really don't want duplicate IDs.
  DCHECK(GetNotification(new_notification->id()) == notifications_.end());
  notifications_.emplace(std::move(new_notification), state);
}

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

NotificationList::Notifications NotificationList::GetNotificationsByNotifierId(
        const NotifierId& notifier_id) {
  Notifications notifications;
  for (const auto& tuple : notifications_) {
    Notification* notification = tuple.first.get();
    if (notification->notifier_id() == notifier_id)
      notifications.insert(notification);
  }
  return notifications;
}

NotificationList::Notifications NotificationList::GetNotificationsByAppId(
    const std::string& app_id) {
  Notifications notifications;
  for (const auto& tuple : notifications_) {
    Notification* notification = tuple.first.get();
    if (notification->notifier_id().id == app_id)
      notifications.insert(notification);
  }
  return notifications;
}

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

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

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

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

bool NotificationList::HasPopupNotifications(
    const NotificationBlockers& blockers) {
  for (const auto& tuple : notifications_) {
    if (tuple.first->priority() < DEFAULT_PRIORITY)
      break;
    if (!tuple.second.shown_as_popup &&
        ShouldShowNotificationAsPopup(*tuple.first, blockers)) {
      return true;
    }
  }
  return false;
}

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

  // Collect notifications that should be shown as popups. Start from oldest.
  for (auto iter = notifications_.rbegin(); iter != notifications_.rend();
       iter++) {
    NotificationState* state = &iter->second;
    Notification* notification = iter->first.get();
    if (state->shown_as_popup)
      continue;

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

    if (!ShouldShowNotificationAsPopup(*notification, blockers)) {
      if (state->is_read)
        state->shown_as_popup = true;
      if (blocked)
        blocked->push_back(notification->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 (notification->priority() == DEFAULT_PRIORITY &&
        default_priority_popup_count++ >= kMaxVisiblePopupNotifications) {
      continue;
    }

    result.insert(notification);
  }
  return result;
}

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

  NotificationState* state = &iter->second;
  const Notification& notification = *iter->first;

  if (iter->second.shown_as_popup)
    return;

  // System notification is marked as shown only when marked as read.
  if (notification.priority() != SYSTEM_PRIORITY || mark_notification_as_read)
    state->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)
    state->is_read = false;
}

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

  NotificationState* state = &iter->second;

  if (state->shown_as_popup)
    return;

  state->is_read = true;
}

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

void NotificationList::SetQuietMode(bool quiet_mode) {
  quiet_mode_ = quiet_mode;
  if (quiet_mode_) {
    for (auto& tuple : notifications_)
      tuple.second.shown_as_popup = true;
  }
}

Notification* NotificationList::GetNotificationById(const std::string& id) {
  auto iter = GetNotification(id);
  if (iter != notifications_.end())
    return iter->first.get();
  return nullptr;
}

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

  return result;
}

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

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

void NotificationList::EraseNotification(OwnedNotifications::iterator iter) {
  notifications_.erase(iter);
}

void NotificationList::PushNotification(
    std::unique_ptr<Notification> notification) {
  // Ensure that notification.id is unique by erasing any existing
  // notification with the same id (shouldn't normally happen).
  auto iter = GetNotification(notification->id());
  NotificationState state;
  if (iter != notifications_.end()) {
    state = iter->second;
    EraseNotification(iter);
  } else {
    // TODO(mukai): needs to distinguish if a notification is dismissed by
    // the quiet mode or user operation.
    state.shown_as_popup =
        message_center_->IsMessageCenterVisible() || quiet_mode_;
  }
  if (notification->priority() == MIN_PRIORITY)
    state.is_read = true;
  notifications_.emplace(std::move(notification), state);
}

}  // namespace message_center
