/*
 *******************************************************************************
 *
 *  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    pointcloud.h
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Main point cloud database class
 * \version 2015-10-14/AW: Initial version
 * \version 2016-11-08/AW: New "fill query" (class QueryFill) added (#1926)
 * \version 2016-11-14/AW: New "invert query" (class QueryInvert) added (#2406)
 * \version 2016-11-16/AW: New function to output database statistics added
 * \version 2017-03-21/AW: Database management interface added (#2550)
 * \version 2017-08-22/AW: Added function to query database UUID (#2720)
 * \version 2018-05-28/AW: New variant of create() that accepts a schema (#3109)
 * \version 2020-02-24/AW: New function to check if a database is empty (#3566)
 * \version 2020-06-29/AW: Database changelog interface added (#3614)
 *
 * Use this class to create or open a point cloud database and insert, update
 * or query points.
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_H
#define RIEGL_RDB_POINTCLOUD_H

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

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

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

#include "riegl/rdb.h"
#include "riegl/rdb/pointcloud/changelog.h"
#include "riegl/rdb/pointcloud/dataTypes.h"
#include "riegl/rdb/pointcloud/pointAttribute.h"
#include "riegl/rdb/pointcloud/createSettings.h"
#include "riegl/rdb/pointcloud/openSettings.h"
#include "riegl/rdb/pointcloud/management.h"
#include "riegl/rdb/pointcloud/metaData.h"
#include "riegl/rdb/pointcloud/pointAttributes.h"
#include "riegl/rdb/pointcloud/transaction.h"
#include "riegl/rdb/pointcloud/transactions.h"
#include "riegl/rdb/pointcloud/graphNode.h"
#include "riegl/rdb/pointcloud/queryStat.h"
#include "riegl/rdb/pointcloud/queryInsert.h"
#include "riegl/rdb/pointcloud/queryUpdate.h"
#include "riegl/rdb/pointcloud/queryRemove.h"
#include "riegl/rdb/pointcloud/querySelect.h"
#include "riegl/rdb/pointcloud/queryFill.h"
#include "riegl/rdb/pointcloud/queryInvert.h"

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

RDB_LIBRARY_API_BEGIN

//______________________________________________________________________________
/*!
 * \brief Create Pointcloud instance
 *
 * This creates a new Pointcloud object instance. To actually access or
 * create a point cloud database file, you must call open() or create().
 *
 * Each Pointcloud instance may only be accessed from one thread/process at
 * a time. Opening the same database using different Pointcloud instances
 * (in the same or different thread or process) is allowed.
 *
 * \note The implicit copy-constructor and assignment-operators will yield
 *       to multiple instances pointing to the same database file. This
 *       is okay, as long as you do not intend to use both instances in
 *       different threads simultaneously.
 *
 * \see rdb_pointcloud_create()
 * \see rdb_pointcloud_open()
 */
RDB_FUNCTION(rdb_pointcloud_new,
    RDBContext     *context,   //!< [in] library context
    RDBPointcloud **pointcloud //!< [out] handle of created object
);

//______________________________________________________________________________
/*!
 * \brief Destroy Pointcloud instance
 *
 * \note If there are multiple Pointcloud instances pointing to the same
 *       file (see constructor notes), then the database file will be
 *       closed when the last Pointcloud instance is deleted.
 */
RDB_FUNCTION(rdb_pointcloud_delete,
    RDBContext     *context,   //!< [in] library context
    RDBPointcloud **pointcloud //!< [in] handle of object to delete
);

//______________________________________________________________________________
/*!
 * \brief Create new database
 *
 * This function creates a new (empty) database. If the given
 * database already exists, it will be overwritten (unless it is
 * opened by other clients, in which case the creation will fail).
 * The target folder must exist - it is not created automatically.
 * If the database could not be created, an exception is thrown.
 */
RDB_FUNCTION(rdb_pointcloud_create,
    RDBContext                  *context,    //!< [in] library context
    RDBPointcloud               *pointcloud, //!< [in] point cloud
    RDBString                    location,   //!< [in] database location (filename)
    RDBPointcloudCreateSettings *settings    //!< [in] database creation settings
);

//______________________________________________________________________________
/*!
 * \brief Create new database
 *
 * \copydoc rdb_pointcloud_create()
 *
 * Additionally, all required point attributes and metadata entries as defined
 * by the schema are added to the database. The schema is given in JSON format,
 * details see rdb_pointcloud_management_validate(). If 'optionals' is not '0',
 * then also the optional point attributes and metadata entries are added to
 * the database.
 *
 * \note
 *   Only RIEGL default point attributes and metadata entries are supported.
 *   Metadata entries are added but have no value (empty string).
 *
 * \note
 *   If the schema defines a primary point attribute, then it overrides
 *   the primary point attribute defined in the 'settings' parameter.
 *
 * \see rdb_pointcloud_management_validate()
 */
RDB_FUNCTION(rdb_pointcloud_create_with_schema,
    RDBContext                  *context,    //!< [in] library context
    RDBPointcloud               *pointcloud, //!< [in] point cloud
    RDBString                    location,   //!< [in] database location (filename)
    RDBPointcloudCreateSettings *settings,   //!< [in] database creation settings
    RDBString                    schema,     //!< [in] database schema (JSON format)
    uint32_t                     optionals   //!< [in] >0: include optional items
);

//______________________________________________________________________________
/*!
 * \brief Open existing database
 *
 * Open existing database location.
 * If the given database does not exist, an exception is thrown.
 */
RDB_FUNCTION(rdb_pointcloud_open,
    RDBContext                *context,    //!< [in] library context
    RDBPointcloud             *pointcloud, //!< [in] point cloud
    RDBString                  location,   //!< [in] database location (filename)
    RDBPointcloudOpenSettings *settings    //!< [in] database open settings
);

//______________________________________________________________________________
/*!
 * \brief Close database
 *
 * Close database file and release all internal resources.
 * This function fails if there are pending transactions.
 */
RDB_FUNCTION(rdb_pointcloud_close,
    RDBContext    *context,   //!< [in] library context
    RDBPointcloud *pointcloud //!< [in] point cloud
);

//______________________________________________________________________________
/*!
 * \brief Check if a database is open
 */
RDB_FUNCTION(rdb_pointcloud_is_open,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud
    uint32_t      *isOpen      //!< [out] 0: not open, 1: open
);

//______________________________________________________________________________
/*!
 * \brief Check if database is empty
 */
RDB_FUNCTION(rdb_pointcloud_is_empty,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud
    uint32_t      *isEmpty     //!< [out] 0: not empty, 1: empty or not open
);

//______________________________________________________________________________
/*!
 * \brief Get database file's UUID
 * \returns the Universally Unique Identifier of the database file
 *
 * \note Database files created with rdblib prior version 2.1.2 do
 *       not have a UUID. In this case the "nil" UUID is returned.
 *       If no database is opened, an empty string is returned.
 */
RDB_FUNCTION(rdb_pointcloud_get_uuid,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud
    RDBString     *result      //!< [out] result string
);

//______________________________________________________________________________
/*!
 * \brief File statistics and debugging information
 *
 * This function returns statistics and debugging information about
 * the database file which is intended for factory usage only (i.e.
 * the format may change at any time and the content is undocumented).
 */
RDB_FUNCTION(rdb_pointcloud_inspect,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud
    const uint8_t  format,     //!< [in] output format
    RDBString     *result      //!< [out] result string
);

//______________________________________________________________________________
/*!
 * \brief Clear internal data cache
 *
 * This function clears (flushes) the internal data cache and reduces
 * memory consumption as much as possible.
 */
RDB_FUNCTION(rdb_pointcloud_clear_cache,
    RDBContext    *context,   //!< [in] library context
    RDBPointcloud *pointcloud //!< [in] point cloud
);

RDB_LIBRARY_API_END

#endif // RIEGL_RDB_POINTCLOUD_H
