/*
 * Copyright (C) Birb Developers
 *
 * Birb is the legal property of its developers, whose names are too numerous
 * to list here. Please refer to the AUTHORS file distributed with this source
 * distribution
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, see <https://www.gnu.org/licenses/>.
 */

#if !defined(BIRB_GLOBAL_HEADER_INSIDE) && !defined(BIRB_COMPILATION)
# error "only <birb.h> may be included directly"
#endif

#ifndef BIRB_QUEUED_OUTPUT_STREAM_H
#define BIRB_QUEUED_OUTPUT_STREAM_H

#include <gio/gio.h>

#include "birbversion.h"

G_BEGIN_DECLS

#define BIRB_QUEUED_OUTPUT_STREAM_ERROR birb_queued_output_stream_error_quark()

/**
 * BirbQueuedOutputStreamError:
 *
 * Error numbers for queued output stream errors.
 *
 * Since: 0.5
 */
typedef enum {
	/**
	 * BIRB_QUEUED_OUTPUT_STREAM_ERROR_GENERIC:
	 *
	 * Generic error, does not yet have an assigned number.
	 *
	 * Since: 0.1
	 */
	BIRB_QUEUED_OUTPUT_STREAM_ERROR_GENERIC BIRB_AVAILABLE_ENUMERATOR_IN_0_1,

	/**
	 * BIRB_QUEUED_OUTPUT_STREAM_ERROR_QUEUE_CLEARED:
	 *
	 * Set on queued tasks when the queue is cleared.
	 *
	 * Since: 0.1
	 */
	BIRB_QUEUED_OUTPUT_STREAM_ERROR_QUEUE_CLEARED BIRB_AVAILABLE_ENUMERATOR_IN_0_1,

	/**
	 * BIRB_QUEUED_OUTPUT_STREAM_ERROR_UNKNOWN_RESULT:
	 *
	 * Used when [method@QueuedOutputStream.push_bytes_finish] is called with a
	 * [iface@Gio.AsyncResult] that was not created by
	 * [method@QueuedOutputStream.push_bytes_async].
	 *
	 * Since: 0.1
	 */
	BIRB_QUEUED_OUTPUT_STREAM_ERROR_UNKNOWN_RESULT BIRB_AVAILABLE_ENUMERATOR_IN_0_1,
} BirbQueuedOutputStreamError;

/**
 * BirbOutputStreamErrorEnum:
 *
 * Error numbers for BirbOutputStream errors.
 *
 * Since: 0.1
 *
 * Deprecated: 0.5: Use [error@QueuedOutputStreamError] instead
 */
typedef BirbQueuedOutputStreamError BirbOutputStreamErrorEnum BIRB_DEPRECATED_TYPE_FOR(BirbQueuedOutputStreamError);

/**
 * birb_queued_output_stream_error_quark:
 *
 * The error domain to identify errors with queued output streams.
 *
 * Returns: The error domain.
 *
 * Since: 0.5
 */
BIRB_AVAILABLE_IN_0_5
GQuark birb_queued_output_stream_error_quark(void);

#define BIRB_TYPE_QUEUED_OUTPUT_STREAM  birb_queued_output_stream_get_type()

/**
 * BirbQueuedOutputStream:
 *
 * An implementation of #GFilterOutputStream which allows queuing data for
 * output. This allows data to be queued while other data is being output.
 * Therefore, data doesn't have to be manually stored while waiting for
 * stream operations to finish.
 *
 * To create a queued output stream, use [ctor@QueuedOutputStream.new].
 *
 * To queue data, use [method@QueuedOutputStream.push_bytes_async].
 *
 * If there's a fatal stream error, it's suggested to clear the remaining bytes
 * queued with [method@QueuedOutputStream.clear_queue] to avoid excessive
 * errors returned in the callback of
 * [method@QueuedOutputStream.push_bytes_async].
 *
 * Since: 0.1
 */
BIRB_AVAILABLE_IN_0_1
G_DECLARE_FINAL_TYPE(BirbQueuedOutputStream, birb_queued_output_stream,
                     BIRB, QUEUED_OUTPUT_STREAM, GFilterOutputStream)

/**
 * birb_queued_output_stream_new:
 * @base_stream: (transfer none): Base output stream to wrap with the queued
 *               stream.
 *
 * Creates a new queued output stream for a base stream.
 *
 * Returns: (transfer full) (type BirbQueuedOutputStream): The new stream.
 *
 * Since: 0.1
 */
BIRB_AVAILABLE_IN_0_1
GOutputStream *birb_queued_output_stream_new(GOutputStream *base_stream);

/**
 * birb_queued_output_stream_push_bytes_async:
 * @stream: The instance.
 * @bytes: (transfer none): The bytes to queue.
 * @priority: IO priority of the request.
 * @cancellable: (nullable): A [class@Gio.Cancellable] or %NULL.
 * @callback: (scope async): Callback to call when the request is finished.
 * @data: Data to pass to @callback.
 *
 * Asynchronously queues and then writes data to @stream. Once the data has
 * been written, or an error occurs, @callback will be called.
 *
 * Be careful such that if there's a fatal stream error, all remaining queued
 * operations will likely return this error. Use
 * [method@Birb.QueuedOutputStream.clear_queue] to clear the queue on such
 * an error to only report it a single time.
 *
 * Since: 0.1
 */
BIRB_AVAILABLE_IN_0_1
void birb_queued_output_stream_push_bytes_async(BirbQueuedOutputStream *stream, GBytes *bytes, int priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data);

/**
 * birb_queued_output_stream_push_bytes_finish:
 * @stream: The instance.
 * @result: The [iface@Gio.AsyncResult] of this operation.
 * @error: Return address for a #GError, or %NULL.
 *
 * Finishes pushing bytes asynchronously.
 *
 * Returns: %TRUE on success, %FALSE if there was an error
 *
 * Since: 0.1
 */
BIRB_AVAILABLE_IN_0_1
gboolean birb_queued_output_stream_push_bytes_finish(BirbQueuedOutputStream *stream, GAsyncResult *result, GError **error);

/**
 * birb_queued_output_stream_clear_queue:
 * @stream: The instance.
 *
 * Clears the queue of any pending bytes. However, any bytes that are in the
 * process of being sent will finish their operation.
 *
 * This function is useful for clearing the queue in case of an IO error. Call
 * this in the async callback in order to clear the queue and avoid having all
 * [method@Birb.QueuedOutputStream.push_bytes_async] calls on @stream return
 * errors if there's a fatal stream error.
 *
 * Since: 0.1
 */
BIRB_AVAILABLE_IN_0_1
void birb_queued_output_stream_clear_queue(BirbQueuedOutputStream *stream);

G_END_DECLS

#endif /* BIRB_QUEUED_OUTPUT_STREAM_H */
