//
//  tb_component_private.h
//  Tightbeam

#ifndef __TIGHTBEAM_COMPONENT_PRIVATE_H
#define __TIGHTBEAM_COMPONENT_PRIVATE_H

#include <stdint.h>

#include <Tightbeam/tightbeam.h>

TB_ASSUME_NONNULL_BEGIN
__TB_BEGIN_DECLS

/*!
 * @typedef tb_component_init_f
 * Component initializer
 *
 * @param cnode
 * A pointer to the CNode containing capabilities for this address space.
 *
 * @param cnode_len
 * The length of the CNode (in bytes).
 *
 * @param data
 * Pointer to the start of initialization data for this component.
 *
 * @param len
 * The length of the buffer pointed to by data (in bytes).
 *
 * @return
 * Returns a pointer to the component object or context to be retained by the
 * runtime. This pointer will be passed to the function present in `release`
 * field of `tb_component_vtable_s` when released by the runtime.
 */
typedef void* _Nonnull (*tb_component_init_f)(const uint8_t * _Nonnull cnode,
        size_t cnode_len, const uint8_t * _Nonnull data, size_t len);

/*!
 * @typedef tb_component_release_f
 *
 * @param object
 * The component object to release, this pointer will be a value that was
 * previously returned from a call to the function present in the `init` field
 * of a component's `tb_component_vtable_s`.
 */
typedef void (*tb_component_release_f)(void *object);

/*!
 * @typedef tb_component_handler_init_f
 * Create a component handler object used to handle requests from a specific
 * client. This object will then become the target of incoming messages
 * received from that client. 
 *
 * In C, the returned handler object is optional
 * given that the incoming messages are routed through the top level handler
 * struct.
 *
 * @param object
 * A pointer to a component object.
 *
 * @return
 * Returns a pointer to the handler object or context to be retained by the
 * runtime. This pointer will be passed to the function pointer in the
 * `handler_release` field of `tb_component_vtable_s` when released.
 */
typedef void* _Nullable (*tb_component_handler_init_f)(void *object);

/*!
 * @typedef tb_component_handler_release_f
 *
 * @param object
 * The component handler object to release, this pointer will be a value that was
 * previously returned from a call to the function present in the `handler_init` field
 * of a component's `tb_component_handler_vtable_s`.
 *
 * @param handler (For C code only)
 * With the lack of objects in C, we maintain a pointer to the component and the
 * client(handler) separately. The object argument will point at
 * the component struct and the handler will point at the handler (client context) struct.
 * The handler pointer will be a value that was previously returned from a call
 * to the function present in the `handler_init` field of a component's
 * `tb_component_handler_vtable_s`.
 */
typedef void (*tb_component_handler_release_f)(void *object, void * _Nullable handler);

/*!
 * @typedef tb_component_handler_destroy_f
 *
 * See parameter description for tb_component_handler_release_f. The destroy
 * function allows you to free any memory associated with the handler object
 * before release is called on it.
 */
typedef void (*tb_component_handler_destroy_f)(void *object, void * _Nullable handler);

/*!
 * @typedef tb_component_handler_decode_f
 * Decode an incoming message for this component and dispatch the decoded
 * method call to `context`.
 *
 * @param service
 * The Tightbeam service connection that owns `msg`.
 *
 * @param query
 * The recieved Tightbeam message.
 *
 * @param component
 * A component object, or context pointer, created by a call into the `init` field of a
 * `tb_component_vtable_s` vtable structure.
 *
 * @param handler
 * A handler object, or context pointer, created by a call to the function pointer in the `handler_init` field
 * of a `tb_component_handler_vtable_s` vtable structure.
 *
 * @param list
 * An optional list of `tb_component_admission_table_s` admission tables. If supplied, the decode
 * function should attempt to enforce admission criteria upon decode.
 *
 * @param list_count
 * The number of admission tables present in `list`, if given.
 *
 * @return
 * Returns the Tightbeam message response to the query, or NULL.
 */
typedef _Nullable tb_message_t (*tb_component_handler_decode_f)(
        tb_service_connection_t service, tb_message_t query, void *component, void * _Nullable handler,
        const tb_component_decode_admission_t * _Nullable __counted_by(list_count) list,
        size_t list_count);

//one vtable for the supertype handler and one for each property
struct tb_component_handler_vtable_s {
    const char * __null_terminated identifier;
    tb_component_handler_init_f handler_init;
    tb_component_handler_release_f handler_release;
    tb_component_handler_destroy_f handler_destroy;
    tb_component_handler_decode_f decode;
};

/*!
 * @struct tb_component_vtable_s
 * A virtual function table specifying the layout of a Tightbeam component's
 * interface to the runtime component manager.
 *
 * @var identifier
 * A unique identifier for this component.
 */
struct tb_component_vtable_s {
    const char * __null_terminated identifier;
    tb_component_init_f init;
    tb_component_release_f release;
    size_t handler_count;
    // Pointer to array of pointers to vtables for each handler
    struct tb_component_handler_vtable_s * _Nonnull * _Nonnull __counted_by(handler_count) handler_vtables;
    struct tb_component_admission_list_s * _Nullable admission_list;
};

/*!
 * Returns a pointer to a capability by offsetting from the capability table base address.
 */
TB_EXPORT
uint64_t
tb_component_capability(const uint8_t * __sized_by(cnode_count) cnode, size_t cnode_count, size_t offset);

__TB_END_DECLS
TB_ASSUME_NONNULL_END

#endif // __TIGHTBEAM_COMPONENT_PRIVATE_H
