// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: Apache-2.0

/// @file ax.h
///
/// @author Nick Avramoussis
///
/// @brief  Single header include which provides methods for initializing AX and
///   running a full AX pipeline (parsing, compiling and executing) across
///   standard OpenVDB Grid types.
///
/// @details  These methods wrap the internal components of OpenVDB AX to
///   provide easier and quick access to running AX code. Users who wish to
///   further optimise and customise the process may interface with these
///   components directly. See the body of the methods provided in this file for
///   example implementations.

#ifndef OPENVDB_AX_AX_HAS_BEEN_INCLUDED
#define OPENVDB_AX_AX_HAS_BEEN_INCLUDED

#include <openvdb_ax/compiler/AttributeBindings.h>
#include <openvdb/openvdb.h>
#include <openvdb/version.h>


namespace openvdb {
OPENVDB_USE_VERSION_NAMESPACE
namespace OPENVDB_VERSION_NAME {
namespace ax {

/// @brief  Initializes OpenVDB AX and subsequent LLVM components.
/// @details  Must be called before any AX compilation or execution is performed.
///           Can be safely called from multiple threads. Cannot be called after
///           uninitialize has been called.
OPENVDB_AX_API void initialize();

/// @brief  Check to see if OpenVDB AX components have been initialized.
/// @note  Can be safely called from multiple threads.
OPENVDB_AX_API bool isInitialized();

/// @brief  Uninitialize and deregister OpenVDB AX.
/// @details  This has the important function of shutting down LLVM and
///           correctly freeing statically allocated LLVM types. Should be
///           called on application termination. Can be safely called from
///           multiple threads.
OPENVDB_AX_API void uninitialize();

////////////////////////////////////////
////////////////////////////////////////

/// @brief  Run a full AX pipeline (parse, compile and execute) on a single
///         OpenVDB Grid.
/// @details  This method wraps the parsing, compilation and execution of AX
///           code for a single OpenVDB grid of any standard grid type
///           (including OpenVDB Points Grids). Provided AX code is expected to
///           only refer to the provided single grid. On success, the grid will
///           have its voxels or point data modified as dictated by the provided
///           AX code.
/// @note  Various defaults are applied to this pipeline to provide a simple
///        run signature. For OpenVDB Numerical grids, only active voxels are
///        processed. For OpenVDB Points grids, all points are processed. Any
///        warnings generated by the parser, compiler or executable will be
///        ignored.
/// @note  Various runtime errors may be thrown from the different AX pipeline
///        stages. See Exceptions.h for the possible different errors.
/// @param  ax    The null terminated AX code string to parse and compile
/// @param  grid  The grid to which to apply the compiled AX function
/// @param  bindings An attribute bindings object mapping names in the AX string to
///                  names of the point attributes/grids (points/volumes resp.)
///                  This can be initialized as a vector of pairs of strings e.g.
///                  {{"axname0","dataname0"}, {"axname1","dataname1"}} see
///                  AttributeBindings.h for details.
OPENVDB_AX_API
void run(const char* ax, openvdb::GridBase& grid,
         const AttributeBindings& bindings = {});

/// @brief  Run a full AX pipeline (parse, compile and execute) on a vector of
///         OpenVDB numerical grids OR a vector of OpenVDB Point Data grids.
/// @details  This method wraps the parsing, compilation and execution of AX
///           code for a vector of OpenVDB grids. The vector must contain either
///           a set of any numerical grids supported by the default AX types OR
///           a set of OpenVDB Points grids. On success, grids in the provided
///           grid vector will be iterated over and updated if they are written
///           to.
/// @warning  The type of grids provided changes the type of AX compilation. If
///           the vector is empty, this function immediately returns with no
///           other effect.
/// @note  Various defaults are applied to this pipeline to provide a simple
///        run signature. For numerical grids, only active voxels are processed
///        and missing grid creation is disabled. For OpenVDB Points grids, all
///        points are processed. Any warnings generated by the parser, compiler
///        or executable will be ignored.
/// @note  Various runtime errors may be thrown from the different AX pipeline
///        stages. See Exceptions.h for the possible different errors.
/// @param  ax     The null terminated AX code string to parse and compile
/// @param  grids  The grids to which to apply the compiled AX function
/// @param  bindings An attribute bindings object mapping names in the AX string to
///                  names of the point attributes/grids (points/volumes resp.)
///                  This can be initialized as a vector of pairs of strings e.g.
///                  {{"axname0","dataname0"}, {"axname1","dataname1"}} see
///                  AttributeBindings.h for details.
OPENVDB_AX_API
void run(const char* ax, openvdb::GridPtrVec& grids,
         const AttributeBindings& bindings = {});

} // namespace ax
} // namespace OPENVDB_VERSION_NAME
} // namespace openvdb

#endif // OPENVDB_AX_AX_HAS_BEEN_INCLUDED

