/******************************************************************************
 * Copyright 2020 NVIDIA Corporation. All rights reserved.
 *****************************************************************************/
/// \file
/// \brief Interface for user-defined distributed computing algorithms

#ifndef NVIDIA_INDEX_IDISTRIBUTED_COMPUTE_ALGORITHM_H
#define NVIDIA_INDEX_IDISTRIBUTED_COMPUTE_ALGORITHM_H

#include <mi/base/types.h>
#include <mi/math/vector.h>
#include <mi/math/color.h>
#include <mi/dice.h>
#include <mi/base/interface_declare.h>

namespace nv
{
namespace index
{

/// Interface class that enables implementing distributed computing algorithms or computing tasks
/// that can operate on the distributed data uploaded to the cluster environment.
///
/// This interface class wraps the DiCE fragmented job interface class and extends it by two
/// additional interface methods: The number of compute units that the distributed computing tasks
/// should be split into (a.k.a. the number of fragments of the fragmented job) needs to be returned
/// by the method \c get_nb_of_fragments(). After running the distributed computing tasks the method
/// \c get_updated_bounding_box needs to return the newly computed bounding box.
///
/// The interface class \c IHeightfield_interaction provides means for invoking a distributed computing
/// task (i.e., the fragmented job) for heightfields internally. Alternatively, the \c
/// IDistributed_compute_algorithm interface class can also be used directly to implement
/// distributed compute tasks working with volume or heightfield data.
///
/// \ingroup nv_index_data_computing
///
class IDistributed_compute_algorithm :
        public mi::base::Interface_declare<0x5e67c454,0x2566,0x4485,0xb3,0xea,0x76,0x86,0x5f,0x67,0x45,0xe6,
                                           mi::neuraylib::IFragmented_job>
{
public:
    /// The number of fragments defines the number of compute units the problem is split into.
    ///
    /// \return     The number of fragments used as parameter to invoke the
    ///             distributed compute tasks, i.e., the fragmented job,
    ///             through the DiCE method \c execute_fragmented().
    ///
    virtual mi::Size get_nb_of_fragments() const = 0;

    /// Returns the bounding box of the scene element associated with the
    /// compute algorithm, which might have been changed by the computation.
    ///
    /// \param[out] bbox    The bounding box that might be changed if the extent
    ///                     of the scene element changes due to the implemented
    ///                     compute algorithm. The bounding box is defined in the
    ///                     scene element's IJK space. Should be initialized with the
    ///                     original bounding box value.
    ///
    virtual void get_updated_bounding_box(
        mi::math::Bbox_struct<mi::Float32, 3>& bbox) const = 0;
};

/// Mixin class for implementing the IDistributed_compute_algorithm interface.
///
/// For convenience, the mixin class leverages the default implementation of the
/// fragmented job mixin class.
///
/// \ingroup nv_index_data_computing
///
template <mi::Uint32 i_id1, mi::Uint16 i_id2, mi::Uint16 i_id3,
          mi::Uint8 i_id4, mi::Uint8 i_id5, mi::Uint8 i_id6, mi::Uint8 i_id7,
          mi::Uint8 i_id8, mi::Uint8 i_id9, mi::Uint8 i_id10, mi::Uint8 i_id11,
          class I = IDistributed_compute_algorithm>
class Distributed_compute_algorithm :
    public mi::neuraylib::Fragmented_job<i_id1,i_id2,i_id3,i_id4,i_id5,i_id6,i_id7,i_id8,i_id9,i_id10,i_id11,I>
{
};


}} // namespace index / nv

#endif // NVIDIA_INDEX_IDISTRIBUTED_COMPUTE_ALGORITHM_H
