// Copyright (c) 2021-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.
//

#include <OgnDelayDatabase.h>
#include <omni/graph/action/IActionGraph.h>

namespace omni
{
namespace graph
{
namespace action
{

namespace
{
    constexpr double kUninitializedStartTime = -1.;
}

class OgnDelay
{
    double m_startTime{ kUninitializedStartTime }; // The value of the context time when we started latent state

public:
    static bool compute(OgnDelayDatabase& db)
    {
        auto iActionGraph = getInterface();
        const auto& contextObj = db.abi_context();
        auto iContext = contextObj.iContext;
        auto& state = db.internalState<OgnDelay>();

        double startTime = state.m_startTime;
        double now = iContext->getTimeSinceStart(contextObj);

        if (state.m_startTime > kUninitializedStartTime)
        {
            // We are being polled, check if we have slept long enough
            double duration = db.inputs.duration();
            duration = std::max(duration, 0.);

            if (now - startTime >= duration)
            {
                state.m_startTime = kUninitializedStartTime;
                iActionGraph->endLatentState(db.getInstanceIndex());
                iActionGraph->setExecutionEnabled(outputs::finished.token(), db.getInstanceIndex());
                return true;
            }
        }
        else
        {
            // This is the first entry, start sleeping
            state.m_startTime = now;
            iActionGraph->startLatentState(db.getInstanceIndex());
            return true;
        }
        // still sleeping

        return true;
    }
};

REGISTER_OGN_NODE()
} // action
} // graph
} // omni
