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

#ifndef UI_MESSAGE_CENTER_NOTIFICATION_LIST_H_
#define UI_MESSAGE_CENTER_NOTIFICATION_LIST_H_

#include <stddef.h>

#include <list>
#include <map>
#include <set>
#include <string>

#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/notification_blocker.h"
#include "ui/message_center/public/cpp/notification_types.h"

namespace base {
class TimeDelta;
}

namespace gfx {
class Image;
}

namespace message_center {

namespace test {
class NotificationListTest;
}

class Notification;
class NotificationDelegate;
struct NotifierId;

// Comparers used to auto-sort the lists of Notifications.
struct MESSAGE_CENTER_EXPORT ComparePriorityTimestampSerial {
  bool operator()(Notification* n1, Notification* n2) const;
};

struct MESSAGE_CENTER_EXPORT CompareTimestampSerial {
  bool operator()(Notification* n1, Notification* n2) const;
};

// An adapter to allow use of the comparers above with std::unique_ptr.
template <typename PlainCompare>
struct UniquePtrCompare {
  template <typename T>
  bool operator()(const std::unique_ptr<T>& n1,
                  const std::unique_ptr<T>& n2) const {
    return PlainCompare()(n1.get(), n2.get());
  }
};

// A helper class to manage the list of notifications.
class MESSAGE_CENTER_EXPORT NotificationList {
 public:
  struct NotificationState {
    bool operator!=(const NotificationState& other) const;

    bool shown_as_popup = false;
    bool is_read = false;
  };

  // Auto-sorted set. Matches the order in which Notifications are shown in
  // Notification Center.
  using Notifications = std::set<Notification*, ComparePriorityTimestampSerial>;
  using OwnedNotifications =
      std::map<std::unique_ptr<Notification>,
               NotificationState,
               UniquePtrCompare<ComparePriorityTimestampSerial>>;

  // Auto-sorted set used to return the Notifications to be shown as popup
  // toasts.
  using PopupNotifications = std::set<Notification*, CompareTimestampSerial>;

  explicit NotificationList(MessageCenter* message_center);
  virtual ~NotificationList();

  // Makes a message "read". Collects the set of ids whose state have changed
  // and set to |udpated_ids|. NULL if updated ids don't matter.
  void SetNotificationsShown(const NotificationBlockers& blockers,
                             std::set<std::string>* updated_ids);

  void AddNotification(std::unique_ptr<Notification> notification);

  void UpdateNotificationMessage(
      const std::string& old_id,
      std::unique_ptr<Notification> new_notification);

  void RemoveNotification(const std::string& id);

  // Returns all notifications that have a matching |notifier_id|.
  Notifications GetNotificationsByNotifierId(const NotifierId& notifier_id);

  // Returns all notifications that have a matching |app_id|.
  Notifications GetNotificationsByAppId(const std::string& app_id);

  // Returns true if the notification exists and was updated.
  bool SetNotificationIcon(const std::string& notification_id,
                           const gfx::Image& image);

  // Returns true if the notification exists and was updated.
  bool SetNotificationImage(const std::string& notification_id,
                            const gfx::Image& image);

  // Returns true if |id| matches a notification in the list and that
  // notification's type matches the given type.
  bool HasNotificationOfType(const std::string& id,
                             const NotificationType type);

  // Returns false if the first notification has been shown as a popup (which
  // means that all notifications have been shown).
  bool HasPopupNotifications(const NotificationBlockers& blockers);

  // Returns the recent notifications of the priority higher then LOW,
  // that have not been shown as a popup. kMaxVisiblePopupNotifications are
  // used to limit the number of notifications for the DEFAULT priority.
  // It also stores the list of notifications which are blocked by |blockers|
  // to |blocked|. |blocked| can be NULL if the caller doesn't care which
  // notifications are blocked.
  PopupNotifications GetPopupNotifications(const NotificationBlockers& blockers,
                                           std::list<std::string>* blocked);

  // Marks a specific popup item as shown. Set |mark_notification_as_read| to
  // true in case marking the notification as read too.
  void MarkSinglePopupAsShown(const std::string& id,
                              bool mark_notification_as_read);

  // Marks a specific popup item as displayed.
  void MarkSinglePopupAsDisplayed(const std::string& id);

  NotificationDelegate* GetNotificationDelegate(const std::string& id);

  bool quiet_mode() const { return quiet_mode_; }

  // Sets the current quiet mode status to |quiet_mode|.
  void SetQuietMode(bool quiet_mode);

  // Sets the current quiet mode to true. The quiet mode will expire in the
  // specified time-delta from now.
  void EnterQuietModeWithExpire(const base::TimeDelta& expires_in);

  // Returns the notification with the corresponding id. If not found, returns
  // NULL. Notification instance is owned by this list.
  Notification* GetNotificationById(const std::string& id);

  void PopupBlocked(const std::string& id);

  // Returns all visible notifications, in a (priority-timestamp) order.
  // Suitable for rendering notifications in a MessageCenter.
  Notifications GetVisibleNotifications(
      const NotificationBlockers& blockers) const;
  size_t NotificationCount(const NotificationBlockers& blockers) const;

 private:
  friend class NotificationListTest;
  FRIEND_TEST_ALL_PREFIXES(NotificationListTest,
                           TestPushingShownNotification);

  // Iterates through the list and returns the first notification matching |id|.
  OwnedNotifications::iterator GetNotification(const std::string& id);

  void EraseNotification(OwnedNotifications::iterator iter);

  void PushNotification(std::unique_ptr<Notification> notification);

  MessageCenter* message_center_;  // owner
  OwnedNotifications notifications_;
  bool quiet_mode_;

  DISALLOW_COPY_AND_ASSIGN(NotificationList);
};

}  // namespace message_center

#endif // UI_MESSAGE_CENTER_NOTIFICATION_LIST_H_
