// Copyright (c) 2019-2021, 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 "OgnPrimDatabase.h"
#include "GraphContext.h"

namespace omni
{
namespace graph
{
namespace core
{
namespace DataModel
{
    //backdoor :(
    void backdoor_copyAttribute(ComputeCacheType& cache, AttrKey dst, AttrKey src);
}

HandleInt nodeCtxHandleToPath(NodeContextHandle const& handle);

class OgnPrim
{

public:

    // copy computed data back to usd prim
    //   This node is used as a placeholder representing a USD prim, which might have connection(s) to upstream node(s).
    //   This data needs to be copied over, so it can be written back to USD
    //   This is a legacy way of doing things. We are using a private backdoor in datamodel to achieve this legacy behavior
    static bool compute(OgnPrimDatabase& db)
    {
        auto& contextObj = db.abi_context();
        GraphContext& contextImpl = *GraphContext::getGraphContextFromHandle(contextObj.contextHandle);
        ComputeCacheType& cache = contextImpl.getCache();
        auto node = db.abi_node();

        ConstAttributeDataHandle const invalidHandle(ConstAttributeDataHandle::invalidValue());

        // find all connected attribute on that node
        size_t countAttr = node.iNode->getAttributeCount(node);
        AttributeObj* attrObjIn = (AttributeObj*)alloca(countAttr * sizeof(AttributeObj));
        AttributeObj* end = attrObjIn + countAttr;
        node.iNode->getAttributes(node, attrObjIn, countAttr);

        auto getHdl = [&contextObj](AttributeObj const& a)
        { return contextObj.iToken->getHandle(a.iAttribute->getName(a)); };

        AttrKey dst{ nodeCtxHandleToPath(node.nodeContextHandle), 0 };
        for (size_t i = 0; i < countAttr; ++i)
        {
            AttrKey src = (AttrKey) attrObjIn[i].iAttribute->getConstAttributeDataHandle(attrObjIn[i]);
            dst.second = getHdl(attrObjIn[i]).token;
            if (dst != src)
                DataModel::backdoor_copyAttribute(cache, dst, src);
        }
        return true;
    }
};

REGISTER_OGN_NODE()

} // namespace core
} // namespace graph
} // namespace omni
