/*
 *******************************************************************************
 *
 *  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    metaData.h
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Manage point cloud meta data
 * \version 2015-10-14/AW: Initial version
 * \version 2018-06-01/AW: New function to validate metadata entry (#3109)
 * \version 2020-03-30/AW: New functions for metadata signatures (#3570)
 *
 * This class allows to manage database-wide properties (aka. "meta-data").
 * Arbitrary properties can be stored in key-value manner along with the
 * point cloud in the database. This might be used for example to store
 * comments, operator/software name or georeferencing information.
 *
 * \see riegl::rdb::Pointcloud::metaData()
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_METADATA_H
#define RIEGL_RDB_POINTCLOUD_METADATA_H

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

#include "riegl/rdb.h"

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

RDB_LIBRARY_API_BEGIN

//______________________________________________________________________________
/*!
 * \brief Query property names
 *
 * \returns a list of property names
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_list,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    uint32_t      *count,      //!< [out] number of names
    RDBString     *list        //!< [out] list of names, separated by \0
);

//______________________________________________________________________________
/*!
 * \brief Check if property exists
 *
 * \note Property names are case sensitive (i.e. "name" and "NAME" are different properties).
 * \returns true if a property with given name exists
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_exists,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBString      name,       //!< [in] property name
    uint32_t      *exists      //!< [out] 0 if property does not exist
);

//______________________________________________________________________________
/*!
 * \brief Set property value
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_set,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBString      name,       //!< [in] property name
    RDBString      value       //!< [in] property value
);

//______________________________________________________________________________
/*!
 * \brief Get property value
 *
 * If the given property name could not be found, the function returns
 * the given default value.
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_get,
    RDBContext    *context,                          //!< [in] library context
    RDBPointcloud *pointcloud,                       //!< [in] point cloud handle
    RDBString      name,                             //!< [in] property name
    RDBString     *value,                            //!< [out] property value
    RDBString      defaultValue RDB_DEFAULT_VALUE(0) //!< [in] default value
);

//______________________________________________________________________________
/*!
 * \brief Delete property
 *
 * If the given property name could not be found, this function does not fail.
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_remove,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBString      name        //!< [in] property name
);

//______________________________________________________________________________
/*!
 * \brief Validate property value
 *
 * This function validates the property given by 'name' against the
 * corresponding built-in schema for RIEGL default metadata entries.
 *
 * If the value does not correspond to the schema, an exception
 * is thrown and the reason can be found in the exception details.
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_validate,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBString      name        //!< [in] name of property to be validated
);

//______________________________________________________________________________
/*!
 * \brief Validate value
 *
 * This function validates the given JSON value against the JSON schema.
 *
 * If the value does not correspond to the schema, an exception
 * is thrown and the reason can be found in the exception details.
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_validate_json,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBString      value,      //!< [in] value to be validated
    RDBString      schema      //!< [in] schema to be validated against
);

//______________________________________________________________________________
/*!
 * \brief Create a signature for a metadata entry.
 *
 * The signature is stored next to the metadata entry in the database file
 * and cannot be read out or modified. A transaction must be started first.
 *
 * Set 'method' to 0 to delete an existing signature ('key_size' and
 * 'key_data' are ignored in this case).
 *
 * \since 2.3.0
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_create_signature,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBString      name,       //!< [in] name of metadata entry to sign
    uint32_t       method,     //!< [in] signature method (0: delete, 1: default)
    uint32_t       key_size,   //!< [in] signature encryption key size (at least 32 byte)
    const void    *key_data    //!< [in] signature encryption key buffer
);

//______________________________________________________________________________
/*!
 * \brief Verify the signature of a metadata entry.
 *
 * Returns 'false' (0) if:
 *
 * - there is no signature for the metadata entry
 * - the signature does not match the current value
 * - a wrong signature encryption key was given
 *
 * Otherwise returns 'true' (1).
 *
 * Set 'method' to 0 to check if a signature exists, no matter if it is
 * valid or not ('key_size' and 'key_data' are ignored in this case).
 *
 * \since 2.3.0
 */
RDB_FUNCTION(rdb_pointcloud_meta_data_verify_signature,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBString      name,       //!< [in] name of metadata entry to verify
    uint32_t       method,     //!< [in] signature method (0: exists, 1: default)
    uint32_t       key_size,   //!< [in] signature encryption key size (at least 32 byte)
    const void    *key_data,   //!< [in] signature encryption key buffer
    uint32_t      *valid       //!< [out] 0 if the signature is not valid
);

RDB_LIBRARY_API_END

#endif // RIEGL_RDB_POINTCLOUD_METADATA_H
