/*
 *******************************************************************************
 *
 *  Copyright 2026 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    queryInsert.h
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Point insert query
 * \version 2015-10-14/AW: Initial version
 * \version 2020-02-27/AW: Add bind_id() for "riegl.id" data buffers (#3576)
 *
 * This class can be used to insert (new) points into the database.
 *
 * \see riegl::rdb::Pointcloud::insert()
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_QUERYINSERT_H
#define RIEGL_RDB_POINTCLOUD_QUERYINSERT_H

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

#include "riegl/rdb.h"

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

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

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

RDB_LIBRARY_API_BEGIN

//______________________________________________________________________________
/*!
 * \brief Constructor
 * \see   riegl::rdb::Pointcloud::insert()
 */
RDB_FUNCTION(rdb_pointcloud_query_insert_new,
    RDBContext                *context,    //!< [in] library context
    RDBPointcloud             *pointcloud, //!< [in] point cloud
    RDBPointcloudQueryInsert **query       //!< [out] query handle
);

//______________________________________________________________________________
/*!
 * \brief Destroy query instance
 */
RDB_FUNCTION(rdb_pointcloud_query_insert_delete,
    RDBContext                *context, //!< [in] library context
    RDBPointcloudQueryInsert **query    //!< [in] query handle
);

//______________________________________________________________________________
/*!
 * \brief Load multi-pass insert settings from JSON string
 *
 * This function can be used to change settings for insert queries
 * in multi-pass insert mode (see 'pointInsertMode' in the database
 * creation settings). To be applied, the settings must be loaded
 * before the first call of next(). For settings that have not been
 * explicitly specified, the default value is used. The settings are
 * not saved in the database. When parsing the JSON string fails, an
 * exception is thrown.
 *
 * Supported settings:
 *
 *     - temporary_file_path (string):
 *       Path of the temporary file; if not specified, null or an
 *       empty string, then the database path with suffix ".temp"
 *       is used.
 *       Default: empty
 *
 *     - points_per_block (integer [1]):
 *       Inserted points are grouped into blocks with this number
 *       of points before they are processed further.
 *       Default: 1048576 (= 16 * 65536)
 *
 *     - initial_voxel_size (float [m]):
 *       Inserted points are grouped into voxels with this edge
 *       length in meters. The value must be a power of two of the
 *       resolution of the point coordinates (usually 0.00025 m).
 *       After all points have been inserted, voxels are combined
 *       or subdivided to achieve the desired maximum number of
 *       points per voxel set in the database creation settings
 *       (see 'chunkSize').
 *       Default: 2.048 m
 *
 * Example JSON string:
 *
 *     {
 *         "temporary_file_path": "",
 *         "points_per_block": 1048576,
 *         "initial_voxel_size": 2.048
 *     }
 *
 * \see riegl::rdb::pointcloud::CreateSettings::pointInsertMode
 * \see riegl::rdb::pointcloud::CreateSettings::chunkSize
 */
RDB_FUNCTION(rdb_pointcloud_query_insert_load_multi_pass_settings,
    RDBContext               *context, //!< [in] library context
    RDBPointcloudQueryInsert *query,   //!< [in] query handle
    RDBString                 json     //!< [in] JSON string
);

//______________________________________________________________________________
/*!
 * \brief Bind attribute buffer
 *
 * Use this function to define a source buffer for a point attribute.
 * Exactly one buffer can be defined for an attribute (i.e. only the
 * most recently defined buffer will be used).
 *
 * You can but don't need to define a buffer for each attribute. If
 * no buffer is defined for an attribute, the attribute's default
 * value will be used instead.
 *
 * The buffer is expected to be n*s*d bytes large, where
 * __n__ is the number of points defined in next(),
 * __s__ is the size of one element as defined by 'dataType' and
 * __d__ is the number of attribute dimensions (elements).
 *
 * \note This function just stores the buffer pointer - it does
 *       __NOT__ copy the data contained in the buffer. So make
 *       sure that the buffer remains valid until you call next().
 *
 * \see riegl::rdb::pointcloud::PointAttributes
 */
RDB_FUNCTION(rdb_pointcloud_query_insert_bind,
    RDBContext               *context,                    //!< [in] library context
    RDBPointcloudQueryInsert *query,                      //!< [in] query handle
    RDBString                 attribute,                  //!< [in] attribute name
    uint32_t                  dataType,                   //!< [in] buffer data type \see dataTypes.h
    const void               *buffer,                     //!< [in] buffer location
    int32_t                   stride RDB_DEFAULT_VALUE(0) //!< [in] bytes between beginnings of successive elements (0: auto)
);

//______________________________________________________________________________
/*!
 * \brief Bind point id buffer
 *
 * If you provide a buffer for the point identifier attribute ("riegl.id"),
 * then it will receive the identifiers of the inserted points (PID). Each
 * point is assigned a unique PID on insertion. The PID starts at 1 for the
 * first point and is incremented by 1 for each subsequent point (so that
 * the PID reflects the insertion order of the points, but only as long as
 * riegl::rdb::pointcloud::CreateSettings::optimizePointID is set to false).
 *
 * \see bind()
 */
RDB_FUNCTION(rdb_pointcloud_query_insert_bind_id,
    RDBContext               *context,                    //!< [in] library context
    RDBPointcloudQueryInsert *query,                      //!< [in] query handle
    uint32_t                  dataType,                   //!< [in] buffer data type \see dataTypes.h
    void                     *buffer,                     //!< [in] buffer location
    int32_t                   stride RDB_DEFAULT_VALUE(0) //!< [in] bytes between beginnings of successive elements (0: auto)
);

//______________________________________________________________________________
/*!
 * \brief Insert points
 *
 * Use this function to actually read the point attributes from
 * all defined buffers and insert the points into the database.
 *
 * Afterwards you may re-fill the buffers or define new buffers
 * with bind() and call next() again until all points have been
 * inserted.
 *
 * \note IEEE-754 "NaN" values contained in floating point source
 *       buffers are ignored and the attribute's default value is
 *       used instead. Furthermore IEEE-754 "Infinity" values will
 *       always cause next() to fail with error code 10414, i.e.
 *       riegl::rdb::Error::QueryAttributeValueOutOfRange.
 *
 * \note Since version 2.4.2, unit vector point attributes (e.g.
 *       "riegl.direction") are automatically normalized (divided
 *       by the vector length) on insertion. This is done for all
 *       point attributes that meet the following requirements:
 *       `length` is 3, `minimumValue` is -1, `maximumValue` is 1,
 *       `resolution` is not 1, `scaleFactor` is 1, `unitSymbol` is
 *       empty, `invalidValue` is undefined and `tags` contains the
 *       "direction" tag but not the "do-not-normalize" tag.
 *
 * \returns the number of points inserted
 */
RDB_FUNCTION(rdb_pointcloud_query_insert_next,
    RDBContext               *context,                       //!< [in] library context
    RDBPointcloudQueryInsert *query,                         //!< [in] query handle
    uint32_t                  count,                         //!< [in] size of source buffers in terms of points
    uint32_t                 *processed RDB_DEFAULT_VALUE(0) //!< [out] number of processed points (optional)
);

RDB_LIBRARY_API_END

#endif // RIEGL_RDB_POINTCLOUD_QUERYINSERT_H
