/*
 *******************************************************************************
 *
 *  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    transactions.h
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Manage point cloud transactions
 * \version 2015-10-14/AW: Initial version
 * \version 2021-11-17/AW: New function to discard transaction data (#3843)
 * \version 2021-11-18/AW: New function to estimate transaction size (#3837)
 *
 * Modifying the point cloud database means to execute a transaction.
 *
 * This class allows to start new transactions (see begin()) and to
 * browse past (already executed) transactions.
 *
 * \see riegl::rdb::Pointcloud::transaction()
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_TRANSACTIONS_H
#define RIEGL_RDB_POINTCLOUD_TRANSACTIONS_H

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

#include "riegl/rdb.h"

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

RDB_LIBRARY_API_BEGIN

//______________________________________________________________________________
/*!
 * \brief Create new transaction
 *
 * Whenever you are going to modify the point cloud, you must create a
 * transaction by using this function. Without a transaction, any function
 * that modifies the point cloud will fail (i.e. it throws an exception).
 *
 * A transaction automatically locks the database so that other users
 * can query data but can __NOT__ add or modify data. Please note that
 * only __one transaction at a time__ is allowed. If there is already
 * a transaction pending, this function will raise an exception (see
 * Error::TransactionPending).
 *
 * To finish a transaction either call commit() or rollback().
 *
 * \note Parameters 'title' and 'agent' are required - i.e. creating
 *       a new transaction will fail if empty strings are provided.
 *       All other parameters are optional.
 *
 * \note Parameters 'comments' and 'settings' serve the user and client
 *       application for information, e.g. to repeat processing steps
 *       later on. They have no influence on the transaction itself. The
 *       client application is free to store information in any format
 *       that is string-compatible (e.g. plain text, INI, XML, JSON).
 *
 * \note The total size of the 'title', 'agent', 'comments' and 'settings'
 *       strings must not exceed 500 MB (bytes, not characters).
 */
RDB_FUNCTION(rdb_pointcloud_transaction_begin,
    RDBContext                 *context,                       //!< [in] library context
    RDBPointcloud              *pointcloud,                    //!< [in] point cloud handle
    RDBString                   title,                         //!< [in] short description, e.g. "Import"
    RDBString                   agent,                         //!< [in] software name, e.g. "rdbimport v1.0"
    RDBString                   comments RDB_DEFAULT_VALUE(0), //!< [in] e.g. process details for humans
    RDBString                   settings RDB_DEFAULT_VALUE(0), //!< [in] e.g. process settings for software
    RDBPointcloudTransactionID *id       RDB_DEFAULT_VALUE(0)  //!< [out] optional transaction ID output
);

//______________________________________________________________________________
/*!
 * \brief Commit current transaction
 *
 * This function commits the current transaction. All changes made by the
 * transaction become visible to others.
 */
RDB_FUNCTION(rdb_pointcloud_transaction_commit,
    RDBContext    *context,   //!< [in] library context
    RDBPointcloud *pointcloud //!< [in] point cloud handle
);

//______________________________________________________________________________
/*!
 * \brief Commit current transaction
 *
 * This function acts like rdb_pointcloud_transaction_commit() and additionally
 * accepts a pointer to a callback function to provide progress information.
 */
RDB_FUNCTION(rdb_pointcloud_transaction_commit_with_progress,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBProgress    progress,   //!< [in] commit progress callback function
    void          *userdata    //!< [in] progress callback function user data
);

//______________________________________________________________________________
/*!
 * \brief Commit current transaction
 *
 * This function acts like rdb_pointcloud_transaction_commit_with_progress()
 * and additionally accepts a transaction signature method and encryption key.
 *
 * \since 2.3.0
 */
RDB_FUNCTION(rdb_pointcloud_transaction_commit_with_signature,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    RDBProgress    progress,   //!< [in] commit progress callback function
    void          *userdata,   //!< [in] progress callback function user data
    uint32_t       signature,  //!< [in] signature method (0: none, 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 Abort current transaction
 *
 * This function rolls back the current transaction and causes all changes
 * made by the transaction to be discarded.
 */
RDB_FUNCTION(rdb_pointcloud_transaction_rollback,
    RDBContext    *context,   //!< [in] library context
    RDBPointcloud *pointcloud //!< [in] point cloud handle
);

//______________________________________________________________________________
/*!
 * \brief Get list of transactions
 *
 * The database keeps a log (journal) of all transactions. This function
 * returns a list of identifiers (IDs) for all recorded transactions.
 */
RDB_FUNCTION(rdb_pointcloud_transaction_list,
    RDBContext                 *context,    //!< [in] library context
    RDBPointcloud              *pointcloud, //!< [in] point cloud handle
    uint32_t                   *count,      //!< [out] number of transactions
    RDBPointcloudTransactionID *list        //!< [out] list of transaction IDs
);

//______________________________________________________________________________
/*!
 * \brief ID of current transaction
 *
 * This function returns the ID of the current transaction. Usually this
 * is the transaction that was committed at last. However, if restore() is
 * used to return to a previous database state, the current transaction is
 * the restored transaction.
 *
 * \note This function does not return the ID of a pending transaction.
 */
RDB_FUNCTION(rdb_pointcloud_transaction_current,
    RDBContext                 *context,    //!< [in] library context
    RDBPointcloud              *pointcloud, //!< [in] point cloud handle
    RDBPointcloudTransactionID *current     //!< [out] ID of current transaction
);

//______________________________________________________________________________
/*!
 * \brief Check if transaction is pending
 *
 * This function checks whether there is a pending transaction that was
 * started by __this__ database instance. This function does __not__ check
 * whether a transaction was started by a different database instance of
 * the current or different thread or process.
 */
RDB_FUNCTION(rdb_pointcloud_transaction_pending,
    RDBContext    *context,    //!< [in] library context
    RDBPointcloud *pointcloud, //!< [in] point cloud handle
    uint32_t      *pending     //!< [out] 0: false, 1: true
);

//______________________________________________________________________________
/*!
 * \brief Query transaction details
 */
RDB_FUNCTION(rdb_pointcloud_transaction_details,
    RDBContext                *context,    //!< [in] library context
    RDBPointcloud             *pointcloud, //!< [in] point cloud handle
    RDBPointcloudTransactionID id,         //!< [in] transaction identifier
    RDBPointcloudTransaction  *transaction //!< [out] transaction details
);

//______________________________________________________________________________
/*!
 * \brief Restore database state
 *
 * This function restores the database state that was current at the end
 * of the transaction. Those transactions that were created after the
 * restored transaction remain valid until a new transaction is created.
 * This offers some simple undo/redo functionality.
 */
RDB_FUNCTION(rdb_pointcloud_transaction_restore,
    RDBContext                *context,    //!< [in] library context
    RDBPointcloud             *pointcloud, //!< [in] point cloud handle
    RDBPointcloudTransactionID id          //!< [in] transaction identifier
);

//______________________________________________________________________________
/*!
 * \brief Discard transaction data
 *
 * This function deletes the given transaction(s). Please note that this
 * operation only removes the transaction(s) from the database history and
 * releases the related data blocks in the database file so that they can
 * be re-used by subsequent transactions. However the database file size
 * will not decrease unless you call vacuum().
 *
 * \note The first (database creation) and the current transaction
 *       (last committed or restored) can not be deleted.
 *
 * \see riegl::rdb::pointcloud::Management::finalize()
 * \see riegl::rdb::pointcloud::Management::vacuum()
 */
RDB_FUNCTION(rdb_pointcloud_transaction_discard,
    RDBContext                       *context,    //!< [in] library context
    RDBPointcloud                    *pointcloud, //!< [in] point cloud handle
    uint32_t                          count,      //!< [in] number of transactions
    const RDBPointcloudTransactionID *list        //!< [in] list of transaction IDs
);

//______________________________________________________________________________
/*!
 * \brief Estimate database size
 *
 * This function returns the size (in bytes) of all data of the specified
 * transactions, which is approximately the file size of a database that
 * contains only these transactions (and no gaps).
 *
 * \note Data blocks may be shared among multiple transactions and size()
 *       returns the total size of the union of all used data blocks. That
 *       is why size(1) + size(2) is not necessarily equal to size(1, 2).
 *
 * \see riegl::rdb::pointcloud::Transactions::discard()
 * \see riegl::rdb::pointcloud::Management::finalize()
 * \see riegl::rdb::pointcloud::Management::vacuum()
 */
RDB_FUNCTION(rdb_pointcloud_transaction_size,
    RDBContext                       *context,    //!< [in] library context
    RDBPointcloud                    *pointcloud, //!< [in] point cloud handle
    uint32_t                          count,      //!< [in] number of transactions
    const RDBPointcloudTransactionID *list,       //!< [in] list of transaction IDs
    uint64_t                         *result      //!< [out] estimated data size [byte]
);

RDB_LIBRARY_API_END

#endif // RIEGL_RDB_POINTCLOUD_TRANSACTIONS_H
