/*
 *******************************************************************************
 *
 *  Copyright 2025 RIEGL Laser Measurement Systems
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *  SPDX-License-Identifier: Apache-2.0
 *
 *******************************************************************************
 */
/*!
 *******************************************************************************
 *
 * \file    context.h
 * \author  RIEGL LMS GmbH, Austria
 * \brief   RDB library context
 * \version 2015-10-14/AW: Initial version
 * \version 2017-01-30/AW: Added function to check if a file is a RDB 2 file
 * \version 2020-09-17/AW: Added function rdb_library_filename()
 * \version 2025-01-21/AW: Added function rdb_object_[un]lock_cf() (#5472)
 * \version 2025-01-29/AW: Added function rdb_context_new_with_api() (#5474)
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_CONTEXT_H
#define RIEGL_RDB_CONTEXT_H

//---< INCLUDES >---------------------------------------------------------------

#include "riegl/rdb.h"

//---< TYPE DEFINITIONS >-------------------------------------------------------

typedef struct RDBContext RDBContext; // forward declaration of implementation details

//---< FUNCTIONS >--------------------------------------------------------------

RDB_LIBRARY_API_BEGIN

//______________________________________________________________________________
/*!
 * \brief Create new library context
 *
 * You need to create a new context before you can call any library function.
 *
 * Use _logPath_ to specify the target folder for RDB log files. If not
 * defined (empty string), then system's folder for temporary files is
 * used (i.e. Windows: "C:\Users\*\AppData\Local\Temp", Linux: "/tmp"). If
 * the given path does not exist, it is not created and logging is disabled.
 *
 * Use _logLevel_ to specify a filter for log messages. Allowed values are
 *
 *   | Level   | Description                |
 *   | ------- | -------------------------- |
 *   | TRACE   | many debug messages        |
 *   | DEBUG   | some debug messages        |
 *   | TEXT    | general messages = default |
 *   | INFO    | hints, information         |
 *   | WARNING | warning messages           |
 *   | ERROR   | error messages             |
 *   | FATAL   | fatal errors               |
 *   | NONE    | no log output at all       |
 *
 * Whereas "TRACE" is the highest log level and means to output everything
 * and "NONE" is the lowest level and means to output nothing. Example:
 * if _logLevel_ is set to "TEXT", debug messages are not output but info,
 * warnings, errors and fatal errors are.
 *
 * Both _logPath_ and _logLevel_ may also be given as environment variables
 * "RDB_LOG_PATH" and "RDB_LOG_LEVEL". Please note that those variables are
 * used only if empty strings are passed to the constructor.
 *
 * \note When the context is deleted, the log file is also deleted but
 *       only if it does not contain WARNING, ERROR or FATAL messages.
 *       To keep the context from deleting the log file, append "!" to
 *       the _logLevel_, e.g. "TEXT!".
 */
RDB_FUNCTION(rdb_context_new,
    RDBContext **context,                       //!< [out] handle of created object
    RDBString    logLevel RDB_DEFAULT_VALUE(0), //!< [in] log level (filter), see description
    RDBString    logPath  RDB_DEFAULT_VALUE(0)  //!< [in] target folder for RDB log files
);
//
RDB_FUNCTION(rdb_context_new_with_api,
    RDBContext **context,                       //!< [out] handle of created object
    RDBString    apiVersion,                    //!< [in] API version string, e.g. "RDB Interface 2.5.2-389b3d29 (C++, Jan 28 2025, 13:15:17)"
    RDBString    logLevel RDB_DEFAULT_VALUE(0), //!< [in] log level (filter), see description
    RDBString    logPath  RDB_DEFAULT_VALUE(0)  //!< [in] target folder for RDB log files
);

//______________________________________________________________________________
/*!
 * \brief Delete library context
 */
RDB_FUNCTION(rdb_context_delete,
    RDBContext **context //!< [in] handle of object to delete
);

//______________________________________________________________________________
/*!
 * \brief Last error details
 *
 * Use this function to query the code and message of the last error.
 */
RDB_FUNCTION(rdb_context_get_last_error,
    RDBContext *context,                      //!< [in] library context
    int32_t    *code,                         //!< [out] error code
    RDBString  *text    RDB_DEFAULT_VALUE(0), //!< [out] error text, set to 0 if not needed
    RDBString  *details RDB_DEFAULT_VALUE(0)  //!< [out] error details, set to 0 if not needed
);

//______________________________________________________________________________
/*!
 * \brief Returns library name
 */
RDB_FUNCTION(rdb_library_name,
    RDBContext *context, //!< [in] library context
    RDBString  *name     //!< [out] library name
);

//______________________________________________________________________________
/*!
 * \brief Returns the name of the file the library was loaded from
 * \since 2.3.0
 */
RDB_FUNCTION(rdb_library_filename,
    RDBContext *context, //!< [in] library context
    RDBString  *filename //!< [out] library filename
);

//______________________________________________________________________________
/*!
 * \brief Returns library version string
 */
RDB_FUNCTION(rdb_library_version,
    RDBContext *context, //!< [in] library context
    RDBString  *version  //!< [out] libary version
);

//______________________________________________________________________________
/*!
 * \brief Returns library license text
 */
RDB_FUNCTION(rdb_library_license,
    RDBContext *context, //!< [in] library context
    RDBString  *license  //!< [out] library license text
);

//______________________________________________________________________________
/*!
 * \brief Database file type title
 *
 * \returns "RDB 2 Database File"
 */
RDB_FUNCTION(rdb_database_file_type_title,
    RDBContext *context, //!< [in] library context
    RDBString  *title    //!< [out] database file type title
);

//______________________________________________________________________________
/*!
 * \brief Database file type suffix
 *
 * \returns "rdbx"
 */
RDB_FUNCTION(rdb_database_file_type_suffix,
    RDBContext *context, //!< [in] library context
    RDBString  *suffix   //!< [out] database file type suffix
);

//______________________________________________________________________________
/*!
 * \brief Check file type
 *
 * \returns true if the given location is a RDB 2 database file.
 */
RDB_FUNCTION(rdb_database_file_type_check,
    RDBContext *context,  //!< [in] library context
    RDBString   location, //!< [in] database location (filename)
    uint32_t   *result    //!< [out] 0: false, 1: true
);

//______________________________________________________________________________
/*!
 * \brief Lock object
 *
 * The specified object is locked for exclusive access, i.e. if the object
 * is already locked by another thread, this function blocks the execution
 * of the calling thread until the object is unlocked by the other thread.
 *
 * If 'object' is null, the function does nothing.
 *
 * Note: This function supports any kind of object, not just RDB objects.
 *
 * \see rdb_object_unlock_cf()
 */
RDB_FUNCTION_CF(rdb_object_lock_cf,
    const void *object //!< [in] the object to be locked
);

//______________________________________________________________________________
/*!
 * \brief Unlock object
 *
 * Release of the exclusive object access lock. This allows one (1)
 * other thread that currently wants to lock the object to continue.
 *
 * If 'object' is null or the object was not previously locked, the
 * function does nothing.
 *
 * \see rdb_object_lock_cf()
 */
RDB_FUNCTION_CF(rdb_object_unlock_cf,
    const void *object //!< [in] the object to be unlocked
);

RDB_LIBRARY_API_END

#endif // RIEGL_RDB_CONTEXT_H
