/* Copyright (C) 2018       Marvin Scholz <epirat07@gmail.com>
 * Copyright (C) 2018-2020  Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#ifndef _LIBIGLOO__IGLOO_H_
#define _LIBIGLOO__IGLOO_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <igloo/ro.h>

/* Gets the version of libigloo.
 *
 * This can be called before any calls to igloo_initialize().
 *
 * All parameters can be NULL to not request the specific value.
 *
 * Parameters:
 *  str
 *      Pointer to a string variable (const char*) used to store the version as a string.
 *  major
 *      Pointer to a int to set the major.
 *  minor
 *      Pointer to a int to set the minor.
 *  patch
 *      Pointer to a int to set the patch.
 * Returns:
 *  igloo_ERROR_NONE if successful or error code otherwise.
 */
igloo_error_t   igloo_version_get(const char **str, int *major, int *minor, int *patch) igloo_ATTR_F_WARN_UNUSED_RESULT;

/* Checks if libigloo is compatible to a given version requirement.
 *
 * Generally using this function should be avoided.
 * igloo_instance_can() should be used whenever possible.
 *
 * This can be called before any calls to igloo_initialize().
 *
 * All parameters can be set to -1 to signal "do not care".
 * If the combination of parameters is invalid false is returned.
 *
 * Typical calls set all max_* parameters to -1.
 *
 *
 * Parameters:
 *  min_major
 *      Minimum major required.
 *  min_minor
 *      Minimum minor required.
 *  min_patch
 *      Minimum patch required.
 *  max_major
 *      Maximum major required.
 *  max_minor
 *      Maximum minor required.
 *  max_patch
 *      Maximum patch required.
 * Returns:
 *  Whether this libigloo is compatible to the request.
 */
bool            igloo_version_check(int min_major, int min_minor, int min_patch, int max_major, int max_minor, int max_patch) igloo_ATTR_F_WARN_UNUSED_RESULT;

/*
 * This initializes libigloo. This MUST BE called before any
 * other functions can be called.
 *
 * Returns a refobject on success or igloo_RO_NULL on failure.
 * This can be called multiple times (e.g. by the application
 * and by the libraries it uses independently).
 *
 * The library is deinitialized when the last reference
 * to a returned object is gone. This happens by
 * calling igloo_ro_unref() on the last reference.
 *
 * All igloo_ro_*() functions can be used on this object.
 */
igloo_error_t   igloo_initialize(igloo_ro_t *instance) igloo_ATTR_F_WARN_UNUSED_RESULT;

/* Check whether libigloo has some specific feature
 *
 * Parameters:
 *  instance
 *      An instance or any object that knows an instance.
 *  feature
 *      The feature to test for.
 * Returns:
 *  Whether the feature is supported.
 */
bool            igloo_instance_can(igloo_ro_t instance, igloo_feature_t *feature) igloo_ATTR_F_WARN_UNUSED_RESULT;

typedef igloo_error_t (igloo_instance_log_handler_t)(igloo_ro_t instance, igloo_ro_t logger, igloo_ro_t msg);
/* Set per-instance logger
 *
 * Note: The instance will only hold a weak reference. So the caller must
 * ensure that there will be a strong reference somewhere else. Otherwise
 * the logger will be released.
 *
 * Parameters:
 *  self
 *      An instance or any object that knows an instance.
 *  logger
 *      The logger to use.
 *  handler
 *      A handler for log messages used to log messages via the logger.
 *      If NULL this call might fail if the type of the logger is not supported.
 * Returns:
 *  igloo_ERROR_NONE if successful or error code otherwise.
 */
igloo_error_t igloo_instance_set_logger(igloo_ro_t self, igloo_ro_t logger, igloo_instance_log_handler_t *handler) igloo_ATTR_F_WARN_UNUSED_RESULT;

/* Get per-instance logger
 *
 * Parameters:
 *  self
 *      An instance or any object that knows an instance.
 *  logger
 *      Pointer to a igloo_ro_t to store the new reference in.
 *      The reference will be a strong reference on success.
 * Returns:
 *  igloo_ERROR_NONE if successful or error code otherwise.
 */
igloo_error_t igloo_instance_get_logger(igloo_ro_t self, igloo_ro_t *logger) igloo_ATTR_F_WARN_UNUSED_RESULT;

/* Log a message with per-instance logger
 *
 * Note: This is much faster than using igloo_instance_get_logger() and
 * using it's return value for single log messages. If you want to push many
 * messages use igloo_instance_get_logger() and igloo_list_forward().
 *
 * Parameters:
 *  self
 *      An instance or any object that knows an instance.
 *  msg
 *      The message to log.
 * Returns:
 *  igloo_ERROR_NONE if successful or error code otherwise.
 */
igloo_error_t igloo_instance_log(igloo_ro_t self, igloo_ro_t msg);

/* Validate an instance.
 *
 * Note: This is very useful when a instance is passed from a user to a library.
 *
 * Parameters:
 *  self
 *      An instance to validate.
 * Returns:
 *  igloo_ERROR_NONE if self is a valid instance, or error code otherwise.
 */
igloo_error_t igloo_instance_validate(igloo_ro_t self) igloo_ATTR_F_WARN_UNUSED_RESULT;

#ifdef __cplusplus
}
#endif

#endif /* ! _LIBIGLOO__IGLOO_H_ */
