{*
 *******************************************************************************
 *
 *  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    riegl.rdb.pointcloud.transactionScope.pas
 * \author  RIEGL LMS GmbH, Austria
 * \brief   Point cloud transaction scope helper class
 * \version 2015-10-14/AW: Initial version
 * \version 2020-07-03/AW: Changelog management interface added (#3614)
 *
 *******************************************************************************
 *}

unit riegl.rdb.pointcloud.transactionScope;

{******************************************************************************}
{***} INTERFACE {**************************************************************}
{******************************************************************************}

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

uses
  riegl.rdb,
  riegl.rdb.progress,
  riegl.rdb.pointcloud,
  riegl.rdb.pointcloud.transaction;

//---< 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
 *}
type
  TRDBTransactionScope = class(System.TObject)
  public
    AutoCommit : Boolean; //!< true: call commit(), false: call rollback() on deletion

    {*!
     * \brief Begin new transaction
     * \see riegl::rdb::pointcloud::Transactions::begin()
     *}
    constructor Create(
      const Pointcloud : TRDBPointcloud; //!< [in] target point cloud object
      const Title      : String;         //!< [in] short description, e.g. "Import"
      const Agent      : String;         //!< [in] software name, e.g. "rdbimport v1.0"
      const Comments   : String = '';    //!< [in] e.g. process details for humans
      const Settings   : String = ''     //!< [in] e.g. process settings for software
    ); reintroduce;

    {*!
     * \brief End transaction
     *}
    destructor Destroy; override;

    {*!
     * \brief Get transaction ID
     * \see riegl::rdb::pointcloud::Transaction::id
     *}
    function ID : TRDBPointcloudTransactionID;

    {*!
     * \brief Commit transaction
     * \see riegl::rdb::pointcloud::Transactions::commit()
     *}
    procedure Commit(
      Progress  : TRDBProgressFunction = nil; //!< [in] commit progress callback function
      Userdata  : Pointer              = nil; //!< [in] progress callback function user data
      Signature : TRDBUInt32           = 0;   //!< [in] signature method (0: none, 1: default)
      KeySize   : TRDBUInt32           = 0;   //!< [in] signature encryption key size (at least 32 byte)
      KeyData   : Pointer              = nil  //!< [in] signature encryption key buffer
    ); overload;
    procedure Commit(
      Progress  : TRDBProgressMethod; //!< [in] commit progress callback method
      Signature : TRDBUInt32 = 0;     //!< [in] signature method (0: none, 1: default)
      KeySize   : TRDBUInt32 = 0;     //!< [in] signature encryption key size (at least 32 byte)
      KeyData   : Pointer    = nil    //!< [in] signature encryption key buffer
    ); overload;
    procedure Commit(
      Signature : TRDBUInt32; //!< [in] signature method (0: none, 1: default)
      KeySize   : TRDBUInt32; //!< [in] signature encryption key size (at least 32 byte)
      KeyData   : Pointer     //!< [in] signature encryption key buffer
    ); overload;

    {*!
     * \brief Rollback transaction
     * \see riegl::rdb::pointcloud::Transactions::rollback()
     *}
    procedure Rollback();

  private
    FTarget : TRDBPointcloud;
    FActive : Boolean;
    FTID    : TRDBPointcloudTransactionID;
  end;

{******************************************************************************}
{***} IMPLEMENTATION {*********************************************************}
{******************************************************************************}

constructor TRDBTransactionScope.Create(
  const Pointcloud : TRDBPointcloud; //!< [in] target point cloud object
  const Title      : String;         //!< [in] short description, e.g. "Import"
  const Agent      : String;         //!< [in] software name, e.g. "rdbimport v1.0"
  const Comments   : String = '';    //!< [in] e.g. process details for humans
  const Settings   : String = ''     //!< [in] e.g. process settings for software
);
begin
  inherited Create;
  AutoCommit := FALSE;
  FTarget    := Pointcloud;
  FActive    := FALSE;
  FTID       := FTarget.Transaction().BeginTransaction(Title, Agent, Comments, Settings);
  FActive    := TRUE;
end;

destructor TRDBTransactionScope.Destroy;
begin
  if (AutoCommit) then
       Commit()
  else Rollback();
  inherited;
end;

function TRDBTransactionScope.ID : TRDBPointcloudTransactionID;
begin
  Result := FTID;
end;

procedure TRDBTransactionScope.Commit(
  Progress  : TRDBProgressFunction;
  Userdata  : Pointer;
  Signature : TRDBUInt32;
  KeySize   : TRDBUInt32;
  KeyData   : Pointer
);
begin
  if (FActive) then
  begin
    FTarget.Transaction().Commit(Progress, Userdata, Signature, KeySize, KeyData);
    FActive := FALSE;
  end;
end;

procedure TRDBTransactionScope.Commit(
  Progress  : TRDBProgressMethod;
  Signature : TRDBUInt32;
  KeySize   : TRDBUInt32;
  KeyData   : Pointer
);
begin
  if (FActive) then
  begin
    FTarget.Transaction().Commit(Progress, Signature, KeySize, KeyData);
    FActive := FALSE;
  end;
end;

procedure TRDBTransactionScope.Commit(
  Signature : TRDBUInt32;
  KeySize   : TRDBUInt32;
  KeyData   : Pointer
);
begin
  Commit(nil, nil, Signature, KeySize, KeyData);
end;

procedure TRDBTransactionScope.Rollback();
begin
  if (FActive) then
  begin
    FTarget.Transaction().Rollback();
    FActive := FALSE;
  end;
end;

end.
