/* SPDX-License-Identifier: BSD-3-Clause */
/**
 * @file
 * @ingroup notify
 * @brief Queues for history, waiting and displayed notifications
 * @copyright Copyright 2013-2014 Sascha Kruse
 * @copyright Copyright 2014-2026 Dunst contributors
 * @license BSD-3-Clause
 *
 * Every method requires to have executed queues_init() at the start.
 *
 * A read only representation of the queue with the current notifications
 * can get acquired by calling queues_get_displayed().
 *
 * When ending the program or resetting the queues, tear down the stack with
 * queues_teardown(). (And reinit with queues_init() if needed.)
 */

#ifndef DUNST_QUEUE_H
#define DUNST_QUEUE_H

#include "dbus.h"
#include "dunst.h"
#include "notification.h"

/**
 * Initialise necessary queues
 *
 * @pre Do not call consecutively to avoid memory leaks
 *      or assure to have queues_teardown() executed before
 */
void queues_init(void);

/**
 * Receive the current list of displayed notifications
 *
 * @return read only list of notifications
 */
GList *queues_get_displayed(void);

/**
 * Recieve the list of all notifications encountered
 *
 * @return read only list of notifications
 */
GList *queues_get_history(void);

/**
 * Get the highest notification in line
 *
 * @return the first notification in waiting
 * @retval NULL if waiting is empty
 */
struct notification *queues_get_head_waiting(void);

/**
 * Returns the current amount of notifications,
 * which are waiting to get displayed
 */
unsigned int queues_length_waiting(void);

/**
 * Returns the current amount of notifications,
 * which are shown in the UI
 */
unsigned int queues_length_displayed(void);

/**
 * Returns the current amount of notifications,
 * which are already in history
 */
unsigned int queues_length_history(void);

/**
 * Insert a fully initialized notification into queues
 *
 * Respects stack_duplicates, and notification replacement
 *
 * @param n the notification to insert
 * @param status the current dunst status
 *
 * - If n->id != 0, n replaces notification n with id n->id
 * - If n->id == 0, n gets a new id assigned
 *
 * @return The new value of `n->id`
 * @retval 0 if the notification was dismissed and freed
 */
int queues_notification_insert(struct notification *n, struct dunst_status status);

/**
 * Replace the notification which matches the id field of
 * the new notification. The given notification is inserted
 * right in the same position as the old notification.
 *
 * @param new replacement for the old notification
 *
 * @retval true if a matching notification has been found and is replaced
 * @retval false otherwise
 */
bool queues_notification_replace_id(struct notification *new);

/**
 * Close the notification that has n->id == id
 *
 * Sends a signal and pushes the selected notification automatically to history.
 *
 * @param id The id of the notification to close
 * @param reason The #reason to close
 *
 * @post Call wake_up() to synchronize the queues with the UI
 *       (which closes the notification on screen)
 */
void queues_notification_close_id(gint id, enum reason reason);

/**
 * Close the given notification.
 * @see queues_notification_close_id()
 *
 * @param n (transfer full) The notification to close
 * @param reason The #reason to close
 */
void queues_notification_close(struct notification *n, enum reason reason);

/**
 * Remove the given notification from all queues
 *
 * Sends a signal and removes the selected notification from all queues.
 *
 * @param n (transfer full) The notification to remove
 * @param reason The #reason to remove
 */
void queues_notification_remove(struct notification *n, enum reason reason);

/**
 * Remove the notification that has n->id == id
 *
 * Sends a signal and removes the selected notification from all queues.
 *
 * @param id The id of the notification to remove
 * @param reason The #reason to remove
 *
 * @post Call wake_up() to synchronize the queues with the UI
 *       (which closes the notification on screen)
 */
void queues_notification_remove_id(gint id, enum reason reason);

/**
 * Removes all notifications from history
 * Returns the number of removed notifications
 */
guint queues_history_clear(void);

/**
 * Pushes the latest notification of history to the displayed queue
 * and removes it from history
 */
void queues_history_pop(void);

/**
 * Pushes the latest notification found in the history buffer identified by
 * it's assigned id
 */
void queues_history_pop_by_id(gint id);

/**
 * Push a single notification to history
 * The given notification has to be removed its queue
 *
 * @param n (transfer full) The notification to push to history
 */
void queues_history_push(struct notification *n);

/**
 * Push all waiting and displayed notifications to history
 */
void queues_history_push_all(void);

/**
 * Removes an notification identified by the given id from the history
 */
bool queues_history_remove_by_id(gint id);

/**
 * Move inserted notifications from waiting queue to displayed queue
 * and show them. In displayed queue, the amount of elements is limited
 * to the amount set via queues_displayed_limit()
 *
 * @post Call wake_up() to synchronize the queues with the UI
 *       (which closes old and shows new notifications on screen)
 *
 * @param status the current status of dunst
 * @param time the current time
 */
void queues_update(struct dunst_status status, gint64 time);

/**
 * Calculate the distance to the next event, when an element in the
 * queues changes
 *
 * @param time the current time
 *
 * @return the timestamp of the next event in the queue, which forces
 *         an update visible to the user. This may be:
 *             - notification hits timeout
 *             - notification's age second changes
 *             - notification's age threshold is hit
 */
gint64 queues_get_next_datachange(gint64 time);

/**
 * Get the notification which has the given id in the displayed and waiting queue or
 * NULL if not found
 *
 * @param id the id searched for.
 *
 * @return the `id` notification  or NULL
 */
struct notification* queues_get_by_id(gint id);

/**
 * Reapply all rules to the queue (used when reloading configs)
 */
void queues_reapply_all_rules(void);

/**
 * Remove all notifications from all list and free the notifications
 *
 * @pre At least one time queues_init() called
 */
void queues_teardown(void);

#endif
