/*
 *******************************************************************************
 *
 *  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    transactionScope.hpp
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Point cloud transaction scope helper class
 * \version 2015-10-14/AW: Initial version
 * \version 2017-11-24/AW: Constructors declared as "explicit" (#2825)
 *
 *******************************************************************************
 */

#ifndef RIEGL_RDB_POINTCLOUD_TRANSACTIONSCOPE_HPP
#define RIEGL_RDB_POINTCLOUD_TRANSACTIONSCOPE_HPP

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

#include "riegl/rdb/pointcloud.hpp"
#include "riegl/rdb/pointcloud/transaction.hpp"

//---< NAMESPACE >--------------------------------------------------------------

namespace riegl {
namespace rdb {
namespace pointcloud {

//---< CLASS TransactionScope >-------------------------------------------------
/*!
 * \brief Point cloud transaction scope helper class
 *
 * This class wraps transaction creation, commit and rollback. It automatically
 * starts a new transaction on construction and either commits or reverts the
 * transaction on deletion. Whether commit() or rollback() is called is defined
 * by variable _autoCommit_, default is false (i.e. rollback).
 *
 * \see riegl::rdb::pointcloud::Transactions
 */
class TransactionScope
{
public:
    bool autoCommit; //!< true: call commit(), false: call rollback() on deletion

    /*!
     * \brief Begin new transaction
     * \see riegl::rdb::pointcloud::Transactions::begin()
     */
    explicit TransactionScope(
        riegl::rdb::Pointcloud &pointcloud,    //!< [in] target point cloud object
        const std::string      &title,         //!< [in] short description, e.g. "Import"
        const std::string      &agent,         //!< [in] software name, e.g. "rdbimport v1.0"
        const std::string      &comments = "", //!< [in] e.g. process details for humans
        const std::string      &settings = ""  //!< [in] e.g. process settings for software

    ):
        autoCommit(false),
        target(pointcloud),
        active(false),
        tid   (0)
    {
        tid = target.transaction().begin(title, agent, comments, settings);
        active = true;
    }

    /*!
     * \brief End transaction
     */
    ~TransactionScope()
    {
        if (autoCommit)
             commit();
        else rollback();
    }

    /*!
     * \brief Get transaction ID
     * \see riegl::rdb::pointcloud::Transaction::id
     */
    Transaction::ID id() const
    {
        return tid;
    }

    /*!
     * \brief Commit transaction
     * \see riegl::rdb::pointcloud::Transactions::commit()
     */
    void commit()
    {
        if (active)
        {
            target.transaction().commit();
            active = false;
        }
    }
    template <typename Callable>
    void commit(Callable &&progress)
    {
        if (active)
        {
            target.transaction().commit(
                std::forward<Callable>(progress)
            );
            active = false;
        }
    }
    template <typename Callable, typename Receiver>
    void commit(Callable &&progress, Receiver &&receiver)
    {
        if (active)
        {
            target.transaction().commit(
                std::forward<Callable>(progress),
                std::forward<Receiver>(receiver)
            );
            active = false;
        }
    }

    /*!
     * \brief Rollback transaction
     * \see riegl::rdb::pointcloud::Transactions::rollback()
     */
    void rollback()
    {
        if (active)
        {
            target.transaction().rollback();
            active = false;
        }
    }

private:
    riegl::rdb::Pointcloud &target;
    bool                    active;
    Transaction::ID         tid;
};

}}} // namespace riegl::rdb::pointcloud

#endif // RIEGL_RDB_POINTCLOUD_TRANSACTIONSCOPE_HPP
