// Copyright (c) 2022-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//

//! @file GraphBuilderContext.h
//!
//! @brief Defines @ref omni::graph::exec::unstable::IGraphBuilderContext.
#pragma once

#include <omni/graph/exec/unstable/Assert.h>
#include <omni/graph/exec/unstable/IGraph.h>
#include <omni/graph/exec/unstable/IGraphBuilder.h>
#include <omni/graph/exec/unstable/IGraphBuilderContext.h>
#include <omni/graph/exec/unstable/IPassPipeline.h>

namespace omni
{
namespace graph
{
namespace exec
{
namespace unstable
{

//! @copydoc omni::graph::exec::unstable::IGraphBuilderContext
template <typename... Bases>
class GraphBuilderContextT : public Implements<Bases...>
{
public:
    //! Construct graph builder context for a given @ref IGraph with a given pass transformation pipeline.
    //!
    //! May throw.
    static omni::core::ObjectPtr<GraphBuilderContextT> create(omni::core::ObjectParam<IGraph> graph,
                                                              omni::core::ObjectParam<IPassPipeline> passPipeline)
    {
        OMNI_THROW_IF_ARG_NULL(graph);
        OMNI_THROW_IF_ARG_NULL(passPipeline);
        return omni::core::steal(new GraphBuilderContextT(graph.get(), passPipeline.get()));
    }

protected:
    //! Core implementation of @ref omni::graph::exec::unstable::IGraphBuilderContext::getConstructionStamp_abi
    Stamp getConstructionStamp_abi() noexcept override
    {
        return m_constructionStamp;
    }

    //! Core implementation of @ref omni::graph::exec::unstable::IGraphBuilderContext::getGraph_abi
    IGraph* getGraph_abi() noexcept override
    {
        return m_owner;
    }

    //! Core implementation of @ref omni::graph::exec::unstable::IGraphBuilderContext::report_abi
    void report_abi(const char* diagnose) noexcept override
    {
        // Default implementation doesn't report anything
    }

    //! Core implementation of @ref omni::graph::exec::unstable::IGraphBuilderContext::runTransformations_abi
    void runTransformations_abi(INodeGraphDef* nodeGraphDef) noexcept override
    {
        m_pipeline->execute(this, nodeGraphDef);
        m_constructionStamp.next();
    }

    //! Constructor
    GraphBuilderContextT(IGraph* graph, IPassPipeline* pipeline)
        : m_owner{ graph }, m_pipeline{ pipeline, omni::core::kBorrow }
    {
    }

private:
    IGraph* m_owner; //!< Owner of all graphs this context touches
    PassPipelinePtr m_pipeline; //!< Graph transformations pipeline used in this context
    Stamp m_constructionStamp; //!< Construction version incremented after pipeline run.
};

//! Core GraphBuilderContext implementation for @ref omni::graph::exec::unstable::IGraphBuilderContext
using GraphBuilderContext = GraphBuilderContextT<IGraphBuilderContext>;

} // namespace unstable
} // namespace exec
} // namespace graph
} // namespace omni
