/*
 *
 * This program 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 program 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.
 */

#ifndef _SH4LT_C_WRITER_H_
#define _SH4LT_C_WRITER_H_

#include <stdlib.h>

#include "./clogger.h"
#include "./cshtype.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef void* Sh4ltWriter;
typedef void* Sh4ltWriterAccess;

/**
 * Construct a Sh4ltWriter.
 *
 * \param   type_desr             A CShType description for the writer.
 * \param   on_client_connect     Callback to be triggered when a follower connects.
 * \param   on_client_disconnect  Callback to be triggered when a follower disconnects.
 * \param   user_data             Pointer to user data passed to connect and disconnect callbacks.
 * \param   log                   Log object where to write internal logs.
 * \param   memsize               Initial size of the shared memory.
 *                                Note the shared memory can be resized at each frame.
 * \param   unix_permission       Permission to apply to the internal Unix socket, shared memory and
 * semaphore.
 *
 * \return the created Sh4ltWriter
 */

Sh4ltWriter sh4lt_make_writer(const Sh4ltShType type_descr,
                              size_t memsize,
                              void (*on_client_connected)(void* user_data, int id),
                              void (*on_client_disconnected)(void* user_data, int id),
                              void* user_data,
                              Sh4ltLogger log,
                              mode_t unix_permission);

/**
 * Delete the Sh4ltWriter and release associated ressources.
 *
 * \param writer The Sh4ltWriter to delete.
 */
void sh4lt_delete_writer(Sh4ltWriter writer);

/**
 * Write with copy and time information.
 *
 * \param writer The Sh4ltWriter.
 * \param data The data to copy.
 * \param size The length of the data to copy.
 * \param buffer_date Playhead date for the beginning of the buffer, in nanoseconds, or -1.
 * \param buffer_duration Buffer duration, in nanoseconds, or -1.
 * \param speed buffer_date clock speed.
 *
 * \return Success of the copy to the shared memory.
 **/
int sh4lt_copy_to_shm(Sh4ltWriter writer,
                      const void* data,
                      size_t size,
                      int64_t buffer_date,
                      int64_t buffer_duration,
                      float speed);

/**
 * Wait for the the readers to finish reading the last buffer.
 *
 * \param writer The Sh4ltWriter.
 * \param timeout_nsec The maximum time to wait in nanoseconds.
 *
 * \return True if readers has finished before timeout, false otherwise.
 *
 */
int sh4lt_wait_readers_for(Sh4ltWriter writer, int64_t timeout_nsec);

// or get write lock and notify clients when they can try locking for reading
Sh4ltWriterAccess sh4lt_get_one_write_access(Sh4ltWriter writer);
Sh4ltWriterAccess sh4lt_get_one_write_access_resize(Sh4ltWriter writer, size_t newsize);
// this will allocate a new uninitialized shared memory space
size_t sh4lt_shm_resize(Sh4ltWriterAccess access, size_t new_size);
void* sh4lt_get_mem(Sh4ltWriterAccess access);
short sh4lt_notify_clients(Sh4ltWriterAccess access,
                           size_t size,
                           int64_t buffer_date,
                           int64_t buffer_duration,
                           float speed);
void sh4lt_release_one_write_access(Sh4ltWriterAccess access);

// Maximum size in bytes for a shared memory segment
unsigned long sh4lt_get_shmmax(Sh4ltLogger log);
// System-wide limit on the number of shared memory segments
unsigned long sh4lt_get_shmmni(Sh4ltLogger log);

#ifdef __cplusplus
}
#endif

#endif
