/*
 * 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_RESPONSE_STREAM_H
#define BIRB_RESPONSE_STREAM_H

#include <gio/gio.h>

#include "birbversion.h"

G_BEGIN_DECLS

#define BIRB_TYPE_RESPONSE_STREAM birb_response_stream_get_type()

/**
 * BirbResponseStream:
 *
 * A subclass of [class@Gio.OutputStream] that can be used for mocking.
 *
 * > Note: Currently only text based streams are supported.
 *
 * This stream lets you automate responses. It is an output stream that can be
 * written to and will scan that for regex patterns in a sequential fashion.
 *
 * If the current regex pattern is found, the associated response will be
 * provided on the input stream and it will start looking for the next pattern.
 *
 * Below is a simple example testing an HTTP GET request that uses the trailing
 * "\r\n\r\n" of the request as the pattern to match.
 *
 * ```c
 * GBytes *bytes = NULL;
 * GBytes *received = NULL;
 * GError *error = NULL;
 * GInputStream *input = NULL;
 * GOutputStream *response = NULL;
 * gconstpointer read_data = NULL;
 * gsize read_data_size = 0;
 *
 * response = birb_response_stream_new();
 * birb_response_stream_add_response(BIRB_RESPONSE_STREAM(response),
 *                                   "\r\n\r\n",
 *                                   "200 OK\r\nContent-Length: 0\r\n\r\n",
 *                                   &error);
 * g_assert_no_error(error);
 *
 * input = birb_response_stream_get_input_stream(BIRB_RESPONSE_STREAM(response));
 *
 * bytes = g_bytes_new_static("GET / HTTP/1.1\r\n\r\n", 18);
 * g_output_stream_write_bytes(response, bytes, NULL, NULL);
 * g_bytes_unref(bytes);
 *
 * received = g_input_stream_read_bytes(input, 4096, NULL, NULL);
 * read_data = g_bytes_get_data(received, &read_data_size);
 * g_assert_cmpmem(read_data, read_data_size,
 *                 "200 OK\r\nContent-Length: 0\r\n\r\n", 29);
 *
 * g_bytes_unref(received);
 *
 * g_object_unref(response);
 * ```
 *
 * Since: 0.6
 */
BIRB_AVAILABLE_IN_0_6
G_DECLARE_FINAL_TYPE(BirbResponseStream, birb_response_stream, BIRB,
                     RESPONSE_STREAM, GOutputStream)

/**
 * birb_response_stream_new:
 *
 * Creates a new response stream.
 *
 * Returns: (transfer full): The new stream.
 *
 * Since: 0.6
 */
BIRB_AVAILABLE_IN_0_6
GOutputStream *birb_response_stream_new(void);

/**
 * birb_response_stream_new_iostream:
 *
 * Creates a new response stream wrapped with [ctor@Gio.SimpleIOStream.new].
 *
 * Returns: (transfer full): The new stream.
 *
 * Since: 0.6
 */
BIRB_AVAILABLE_IN_0_6
GIOStream *birb_response_stream_new_iostream(void);

/**
 * birb_response_stream_add_response:
 * @pattern: (nullable): the regex pattern to match
 * @response: (nullable): the response to send
 * @error: (out) (nullable): a return address for a #GError
 *
 * Adds the given regex @pattern and @response pair.
 *
 * If @pattern is %NULL, @response will be emitted immediately.
 *
 * If @response is %NULL, no data will be written to the output stream. This is
 * useful if you want to easily match multiple inputs before responding.
 *
 * Returns: true if the regex pattern was valid and added successfully.
 *
 * Since: 0.6
 */
BIRB_AVAILABLE_IN_0_6
gboolean birb_response_stream_add_response(BirbResponseStream *stream, const char *pattern, const char *response, GError **error);

/**
 * birb_response_stream_get_input_stream:
 *
 * Gets the input stream.
 *
 * This stream should be used as the normal input stream you would read from.
 *
 * Returns: (transfer none): The input stream.
 *
 * Since: 0.6
 */
BIRB_AVAILABLE_IN_0_6
GInputStream *birb_response_stream_get_input_stream(BirbResponseStream *stream);

G_END_DECLS

#endif /* BIRB_RESPONSE_STREAM_H */
