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

namespace omni {
namespace graph {
namespace test {


class OgnTestAllDataTypes
{
public:
    static bool compute(OgnTestAllDataTypesDatabase& db)
    {
        if (db.inputs.doNotCompute())
        {
            return true;
        }

        db.outputs.a_bool() = db.inputs.a_bool();
        db.outputs.a_bool_array() = db.inputs.a_bool_array();

        db.outputs.a_colord_3() = db.inputs.a_colord_3();
        db.outputs.a_colord_4() = db.inputs.a_colord_4();
        db.outputs.a_colorf_3() = db.inputs.a_colorf_3();
        db.outputs.a_colorf_4() = db.inputs.a_colorf_4();
        db.outputs.a_colorh_3() = db.inputs.a_colorh_3();
        db.outputs.a_colorh_4() = db.inputs.a_colorh_4();
        db.outputs.a_colord_3_array() = db.inputs.a_colord_3_array();
        db.outputs.a_colord_4_array() = db.inputs.a_colord_4_array();
        db.outputs.a_colorf_3_array() = db.inputs.a_colorf_3_array();
        db.outputs.a_colorf_4_array() = db.inputs.a_colorf_4_array();
        db.outputs.a_colorh_3_array() = db.inputs.a_colorh_3_array();
        db.outputs.a_colorh_4_array() = db.inputs.a_colorh_4_array();

        db.outputs.a_double() = db.inputs.a_double();
        db.outputs.a_double_2() = db.inputs.a_double_2();
        db.outputs.a_double_3() = db.inputs.a_double_3();
        db.outputs.a_double_4() = db.inputs.a_double_4();
        db.outputs.a_double_array() = db.inputs.a_double_array();
        db.outputs.a_double_2_array() = db.inputs.a_double_2_array();
        db.outputs.a_double_3_array() = db.inputs.a_double_3_array();
        db.outputs.a_double_4_array() = db.inputs.a_double_4_array();

        db.outputs.a_execution() = db.inputs.a_execution();

        db.outputs.a_float() = db.inputs.a_float();
        db.outputs.a_float_2() = db.inputs.a_float_2();
        db.outputs.a_float_3() = db.inputs.a_float_3();
        db.outputs.a_float_4() = db.inputs.a_float_4();
        db.outputs.a_float_array() = db.inputs.a_float_array();
        db.outputs.a_float_2_array() = db.inputs.a_float_2_array();
        db.outputs.a_float_3_array() = db.inputs.a_float_3_array();
        db.outputs.a_float_4_array() = db.inputs.a_float_4_array();

        db.outputs.a_frame_4() = db.inputs.a_frame_4();
        db.outputs.a_frame_4_array() = db.inputs.a_frame_4_array();

        db.outputs.a_half() = db.inputs.a_half();
        db.outputs.a_half_2() = db.inputs.a_half_2();
        db.outputs.a_half_3() = db.inputs.a_half_3();
        db.outputs.a_half_4() = db.inputs.a_half_4();
        db.outputs.a_half_array() = db.inputs.a_half_array();
        db.outputs.a_half_2_array() = db.inputs.a_half_2_array();
        db.outputs.a_half_3_array() = db.inputs.a_half_3_array();
        db.outputs.a_half_4_array() = db.inputs.a_half_4_array();

        db.outputs.a_int() = db.inputs.a_int();
        db.outputs.a_int_2() = db.inputs.a_int_2();
        db.outputs.a_int_3() = db.inputs.a_int_3();
        db.outputs.a_int_4() = db.inputs.a_int_4();
        db.outputs.a_int_array() = db.inputs.a_int_array();
        db.outputs.a_int_2_array() = db.inputs.a_int_2_array();
        db.outputs.a_int_3_array() = db.inputs.a_int_3_array();
        db.outputs.a_int_4_array() = db.inputs.a_int_4_array();

        db.outputs.a_int64() = db.inputs.a_int64();
        db.outputs.a_int64_array() = db.inputs.a_int64_array();

        db.outputs.a_matrixd_2() = db.inputs.a_matrixd_2();
        db.outputs.a_matrixd_3() = db.inputs.a_matrixd_3();
        db.outputs.a_matrixd_4() = db.inputs.a_matrixd_4();
        db.outputs.a_matrixd_2_array() = db.inputs.a_matrixd_2_array();
        db.outputs.a_matrixd_3_array() = db.inputs.a_matrixd_3_array();
        db.outputs.a_matrixd_4_array() = db.inputs.a_matrixd_4_array();

        db.outputs.a_normald_3() = db.inputs.a_normald_3();
        db.outputs.a_normalf_3() = db.inputs.a_normalf_3();
        db.outputs.a_normalh_3() = db.inputs.a_normalh_3();
        db.outputs.a_normald_3_array() = db.inputs.a_normald_3_array();
        db.outputs.a_normalf_3_array() = db.inputs.a_normalf_3_array();
        db.outputs.a_normalh_3_array() = db.inputs.a_normalh_3_array();

        db.outputs.a_objectId() = db.inputs.a_objectId();
        db.outputs.a_objectId_array() = db.inputs.a_objectId_array();

        db.outputs.a_path() = db.inputs.a_path();

        db.outputs.a_pointd_3() = db.inputs.a_pointd_3();
        db.outputs.a_pointf_3() = db.inputs.a_pointf_3();
        db.outputs.a_pointh_3() = db.inputs.a_pointh_3();
        db.outputs.a_pointd_3_array() = db.inputs.a_pointd_3_array();
        db.outputs.a_pointf_3_array() = db.inputs.a_pointf_3_array();
        db.outputs.a_pointh_3_array() = db.inputs.a_pointh_3_array();

        db.outputs.a_quatd_4() = db.inputs.a_quatd_4();
        db.outputs.a_quatf_4() = db.inputs.a_quatf_4();
        db.outputs.a_quath_4() = db.inputs.a_quath_4();
        db.outputs.a_quatd_4_array() = db.inputs.a_quatd_4_array();
        db.outputs.a_quatf_4_array() = db.inputs.a_quatf_4_array();
        db.outputs.a_quath_4_array() = db.inputs.a_quath_4_array();

        db.outputs.a_string() = db.inputs.a_string();

        db.outputs.a_target() = db.inputs.a_target();

        db.outputs.a_texcoordd_2() = db.inputs.a_texcoordd_2();
        db.outputs.a_texcoordd_3() = db.inputs.a_texcoordd_3();
        db.outputs.a_texcoordf_2() = db.inputs.a_texcoordf_2();
        db.outputs.a_texcoordf_3() = db.inputs.a_texcoordf_3();
        db.outputs.a_texcoordh_2() = db.inputs.a_texcoordh_2();
        db.outputs.a_texcoordh_3() = db.inputs.a_texcoordh_3();
        db.outputs.a_texcoordd_2_array() = db.inputs.a_texcoordd_2_array();
        db.outputs.a_texcoordd_3_array() = db.inputs.a_texcoordd_3_array();
        db.outputs.a_texcoordf_2_array() = db.inputs.a_texcoordf_2_array();
        db.outputs.a_texcoordf_3_array() = db.inputs.a_texcoordf_3_array();
        db.outputs.a_texcoordh_2_array() = db.inputs.a_texcoordh_2_array();
        db.outputs.a_texcoordh_3_array() = db.inputs.a_texcoordh_3_array();

        db.outputs.a_timecode() = db.inputs.a_timecode();
        db.outputs.a_timecode_array() = db.inputs.a_timecode_array();

        db.outputs.a_token() = db.inputs.a_token();
        db.outputs.a_token_array() = db.inputs.a_token_array();

        db.outputs.a_uchar() = db.inputs.a_uchar();
        db.outputs.a_uchar_array() = db.inputs.a_uchar_array();

        db.outputs.a_uint() = db.inputs.a_uint();
        db.outputs.a_uint_array() = db.inputs.a_uint_array();

        db.outputs.a_uint64() = db.inputs.a_uint64();
        db.outputs.a_uint64_array() = db.inputs.a_uint64_array();

        db.outputs.a_vectord_3() = db.inputs.a_vectord_3();
        db.outputs.a_vectorf_3() = db.inputs.a_vectorf_3();
        db.outputs.a_vectorh_3() = db.inputs.a_vectorh_3();
        db.outputs.a_vectord_3_array() = db.inputs.a_vectord_3_array();
        db.outputs.a_vectorf_3_array() = db.inputs.a_vectorf_3_array();
        db.outputs.a_vectorh_3_array() = db.inputs.a_vectorh_3_array();

        // The input bundle could contain any of the legal data types so check them all. When a match is found then
        // a copy of the regular input attribute with the same type is added to both the state and output bundles.
        // As a secondary check it also does type casting to USD types where explicit casting has been implemented.
        auto& outputBundle = db.outputs.a_bundle();
        auto& stateBundle = db.state.a_bundle();
        for (const auto& bundledAttribute : db.inputs.a_bundle())
        {
            const auto& bundledType = bundledAttribute.type();

            // As the copyData handles attributes of all types, and we are by design creating an attribute with a type
            // identical to the one it is copying, none of the usual bundle member casting is necessary. A simple
            // create-and-copy gives a bundle with contents equal to all of the input attributes.
            auto newOutput = outputBundle.addAttribute(bundledAttribute.name(), bundledType);
            auto newState = stateBundle.addAttribute(bundledAttribute.name(), bundledType);
            newOutput.copyData(bundledAttribute);
            newState.copyData(bundledAttribute);
        }

        // State attributes take on the input values the first time they evaluate, zeroes on subsequent evaluations.
        // The a_firstEvaluation attribute is used as the gating state information to decide when evaluation needs to happen again.
        if (db.state.a_firstEvaluation())
        {
            db.state.a_firstEvaluation() = false;
            db.state.a_bool() = db.inputs.a_bool();
            db.state.a_bool_array() = db.inputs.a_bool_array();

            db.state.a_colord_3() = db.inputs.a_colord_3();
            db.state.a_colord_4() = db.inputs.a_colord_4();
            db.state.a_colorf_3() = db.inputs.a_colorf_3();
            db.state.a_colorf_4() = db.inputs.a_colorf_4();
            db.state.a_colorh_3() = db.inputs.a_colorh_3();
            db.state.a_colorh_4() = db.inputs.a_colorh_4();
            db.state.a_colord_3_array() = db.inputs.a_colord_3_array();
            db.state.a_colord_4_array() = db.inputs.a_colord_4_array();
            db.state.a_colorf_3_array() = db.inputs.a_colorf_3_array();
            db.state.a_colorf_4_array() = db.inputs.a_colorf_4_array();
            db.state.a_colorh_3_array() = db.inputs.a_colorh_3_array();
            db.state.a_colorh_4_array() = db.inputs.a_colorh_4_array();

            db.state.a_double() = db.inputs.a_double();
            db.state.a_double_2() = db.inputs.a_double_2();
            db.state.a_double_3() = db.inputs.a_double_3();
            db.state.a_double_4() = db.inputs.a_double_4();
            db.state.a_double_array() = db.inputs.a_double_array();
            db.state.a_double_2_array() = db.inputs.a_double_2_array();
            db.state.a_double_3_array() = db.inputs.a_double_3_array();
            db.state.a_double_4_array() = db.inputs.a_double_4_array();

            db.state.a_execution() = db.inputs.a_execution();

            db.state.a_float() = db.inputs.a_float();
            db.state.a_float_2() = db.inputs.a_float_2();
            db.state.a_float_3() = db.inputs.a_float_3();
            db.state.a_float_4() = db.inputs.a_float_4();
            db.state.a_float_array() = db.inputs.a_float_array();
            db.state.a_float_2_array() = db.inputs.a_float_2_array();
            db.state.a_float_3_array() = db.inputs.a_float_3_array();
            db.state.a_float_4_array() = db.inputs.a_float_4_array();

            db.state.a_frame_4() = db.inputs.a_frame_4();
            db.state.a_frame_4_array() = db.inputs.a_frame_4_array();

            db.state.a_half() = db.inputs.a_half();
            db.state.a_half_2() = db.inputs.a_half_2();
            db.state.a_half_3() = db.inputs.a_half_3();
            db.state.a_half_4() = db.inputs.a_half_4();
            db.state.a_half_array() = db.inputs.a_half_array();
            db.state.a_half_2_array() = db.inputs.a_half_2_array();
            db.state.a_half_3_array() = db.inputs.a_half_3_array();
            db.state.a_half_4_array() = db.inputs.a_half_4_array();

            db.state.a_int() = db.inputs.a_int();
            db.state.a_int_2() = db.inputs.a_int_2();
            db.state.a_int_3() = db.inputs.a_int_3();
            db.state.a_int_4() = db.inputs.a_int_4();
            db.state.a_int_array() = db.inputs.a_int_array();
            db.state.a_int_2_array() = db.inputs.a_int_2_array();
            db.state.a_int_3_array() = db.inputs.a_int_3_array();
            db.state.a_int_4_array() = db.inputs.a_int_4_array();

            db.state.a_int64() = db.inputs.a_int64();
            db.state.a_int64_array() = db.inputs.a_int64_array();

            db.state.a_matrixd_2() = db.inputs.a_matrixd_2();
            db.state.a_matrixd_3() = db.inputs.a_matrixd_3();
            db.state.a_matrixd_4() = db.inputs.a_matrixd_4();
            db.state.a_matrixd_2_array() = db.inputs.a_matrixd_2_array();
            db.state.a_matrixd_3_array() = db.inputs.a_matrixd_3_array();
            db.state.a_matrixd_4_array() = db.inputs.a_matrixd_4_array();

            db.state.a_normald_3() = db.inputs.a_normald_3();
            db.state.a_normalf_3() = db.inputs.a_normalf_3();
            db.state.a_normalh_3() = db.inputs.a_normalh_3();
            db.state.a_normald_3_array() = db.inputs.a_normald_3_array();
            db.state.a_normalf_3_array() = db.inputs.a_normalf_3_array();
            db.state.a_normalh_3_array() = db.inputs.a_normalh_3_array();

            db.state.a_objectId() = db.inputs.a_objectId();
            db.state.a_objectId_array() = db.inputs.a_objectId_array();

            db.state.a_path() = db.inputs.a_path();
            db.state.a_pointd_3() = db.inputs.a_pointd_3();
            db.state.a_pointf_3() = db.inputs.a_pointf_3();
            db.state.a_pointh_3() = db.inputs.a_pointh_3();
            db.state.a_pointd_3_array() = db.inputs.a_pointd_3_array();
            db.state.a_pointf_3_array() = db.inputs.a_pointf_3_array();
            db.state.a_pointh_3_array() = db.inputs.a_pointh_3_array();

            db.state.a_quatd_4() = db.inputs.a_quatd_4();
            db.state.a_quatf_4() = db.inputs.a_quatf_4();
            db.state.a_quath_4() = db.inputs.a_quath_4();
            db.state.a_quatd_4_array() = db.inputs.a_quatd_4_array();
            db.state.a_quatf_4_array() = db.inputs.a_quatf_4_array();
            db.state.a_quath_4_array() = db.inputs.a_quath_4_array();

            db.state.a_string() = db.inputs.a_string();
            db.state.a_stringEmpty() = db.inputs.a_string();

            db.state.a_target() = db.inputs.a_target();

            db.state.a_texcoordd_2() = db.inputs.a_texcoordd_2();
            db.state.a_texcoordd_3() = db.inputs.a_texcoordd_3();
            db.state.a_texcoordf_2() = db.inputs.a_texcoordf_2();
            db.state.a_texcoordf_3() = db.inputs.a_texcoordf_3();
            db.state.a_texcoordh_2() = db.inputs.a_texcoordh_2();
            db.state.a_texcoordh_3() = db.inputs.a_texcoordh_3();
            db.state.a_texcoordd_2_array() = db.inputs.a_texcoordd_2_array();
            db.state.a_texcoordd_3_array() = db.inputs.a_texcoordd_3_array();
            db.state.a_texcoordf_2_array() = db.inputs.a_texcoordf_2_array();
            db.state.a_texcoordf_3_array() = db.inputs.a_texcoordf_3_array();
            db.state.a_texcoordh_2_array() = db.inputs.a_texcoordh_2_array();
            db.state.a_texcoordh_3_array() = db.inputs.a_texcoordh_3_array();

            db.state.a_timecode() = db.inputs.a_timecode();
            db.state.a_timecode_array() = db.inputs.a_timecode_array();

            db.state.a_token() = db.inputs.a_token();
            db.state.a_token_array() = db.inputs.a_token_array();

            db.state.a_uchar() = db.inputs.a_uchar();
            db.state.a_uchar_array() = db.inputs.a_uchar_array();

            db.state.a_uint() = db.inputs.a_uint();
            db.state.a_uint_array() = db.inputs.a_uint_array();

            db.state.a_uint64() = db.inputs.a_uint64();
            db.state.a_uint64_array() = db.inputs.a_uint64_array();

            db.state.a_vectord_3() = db.inputs.a_vectord_3();
            db.state.a_vectorf_3() = db.inputs.a_vectorf_3();
            db.state.a_vectorh_3() = db.inputs.a_vectorh_3();
            db.state.a_vectord_3_array() = db.inputs.a_vectord_3_array();
            db.state.a_vectorf_3_array() = db.inputs.a_vectorf_3_array();
            db.state.a_vectorh_3_array() = db.inputs.a_vectorh_3_array();
        }
        else
        {
            // On subsequent evaluations the state values are all set to 0 (empty list for array types)
            db.state.a_bool() = false;
            db.state.a_bool_array.resize(0);

            db.state.a_colord_3().Set(0.0, 0.0, 0.0);
            db.state.a_colord_4().Set(0.0, 0.0, 0.0, 0.0);
            db.state.a_colorf_3().Set(0.0, 0.0, 0.0);
            db.state.a_colorf_4().Set(0.0, 0.0, 0.0, 0.0);
            db.state.a_colorh_3() *= 0.0;
            db.state.a_colorh_4() *= 0.0;
            db.state.a_colord_3_array.resize(0);
            db.state.a_colord_4_array.resize(0);
            db.state.a_colorf_3_array.resize(0);
            db.state.a_colorf_4_array.resize(0);
            db.state.a_colorh_3_array.resize(0);
            db.state.a_colorh_4_array.resize(0);

            db.state.a_double() = 0.0;
            db.state.a_double_2().Set(0.0, 0.0);
            db.state.a_double_3().Set(0.0, 0.0, 0.0);
            db.state.a_double_4().Set(0.0, 0.0, 0.0, 0.0);
            db.state.a_double_array.resize(0);
            db.state.a_double_2_array.resize(0);
            db.state.a_double_3_array.resize(0);
            db.state.a_double_4_array.resize(0);

            db.state.a_execution() = 0;

            db.state.a_float() = 0.0f;
            db.state.a_float_2().Set(0.0f, 0.0f);
            db.state.a_float_3().Set(0.0f, 0.0f, 0.0f);
            db.state.a_float_4().Set(0.0f, 0.0f, 0.0f, 0.0f);
            db.state.a_float_array.resize(0);
            db.state.a_float_2_array.resize(0);
            db.state.a_float_3_array.resize(0);
            db.state.a_float_4_array.resize(0);

            db.state.a_frame_4().SetZero();
            db.state.a_frame_4_array.resize(0);

            db.state.a_half() = pxr::GfHalf(0.0);
            db.state.a_half_2() *= 0.0;
            db.state.a_half_3() *= 0.0;
            db.state.a_half_4() *= 0.0;
            db.state.a_half_array.resize(0);
            db.state.a_half_2_array.resize(0);
            db.state.a_half_3_array.resize(0);
            db.state.a_half_4_array.resize(0);

            db.state.a_int() = 0;
            db.state.a_int_2().Set(0, 0);
            db.state.a_int_3().Set(0, 0, 0);
            db.state.a_int_4().Set(0, 0, 0, 0);
            db.state.a_int_array.resize(0);
            db.state.a_int_2_array.resize(0);
            db.state.a_int_3_array.resize(0);
            db.state.a_int_4_array.resize(0);

            db.state.a_int64() = 0;
            db.state.a_int64_array.resize(0);

            db.state.a_matrixd_2().SetZero();
            db.state.a_matrixd_3().SetZero();
            db.state.a_matrixd_4().SetZero();
            db.state.a_matrixd_2_array.resize(0);
            db.state.a_matrixd_3_array.resize(0);
            db.state.a_matrixd_4_array.resize(0);

            db.state.a_normald_3().Set(0.0, 0.0, 0.0);
            db.state.a_normalf_3().Set(0.0f, 0.0f, 0.0f);
            db.state.a_normalh_3() *= 0.0;
            db.state.a_normald_3_array.resize(0);
            db.state.a_normalf_3_array.resize(0);
            db.state.a_normalh_3_array.resize(0);

            db.state.a_objectId() = 0;
            db.state.a_objectId_array.resize(0);

            std::string emptyString;
            db.state.a_path() = emptyString;
            db.state.a_pointd_3().Set(0.0, 0.0, 0.0);
            db.state.a_pointf_3().Set(0.0f, 0.0f, 0.0f);
            db.state.a_pointh_3() *= 0.0;
            db.state.a_pointd_3_array.resize(0);
            db.state.a_pointf_3_array.resize(0);
            db.state.a_pointh_3_array.resize(0);

            db.state.a_quatd_4().SetReal(0.0);
            db.state.a_quatd_4().SetImaginary(0.0, 0.0, 0.0);
            db.state.a_quatf_4().SetReal(0.0f);
            db.state.a_quatf_4().SetImaginary(0.0f, 0.0f, 0.0f);
            db.state.a_quath_4() *= 0.0;
            db.state.a_quatd_4_array.resize(0);
            db.state.a_quatf_4_array.resize(0);
            db.state.a_quath_4_array.resize(0);

            db.state.a_string() = "";
        
            db.state.a_target().resize(0);

            db.state.a_texcoordd_2().Set(0.0, 0.0);
            db.state.a_texcoordd_3().Set(0.0, 0.0, 0.0);
            db.state.a_texcoordf_2().Set(0.0f, 0.0f);
            db.state.a_texcoordf_3().Set(0.0f, 0.0f, 0.0f);
            db.state.a_texcoordh_2() *= 0.0;
            db.state.a_texcoordh_3() *= 0.0;
            db.state.a_texcoordd_2_array.resize(0);
            db.state.a_texcoordd_3_array.resize(0);
            db.state.a_texcoordf_2_array.resize(0);
            db.state.a_texcoordf_3_array.resize(0);
            db.state.a_texcoordh_2_array.resize(0);
            db.state.a_texcoordh_3_array.resize(0);

            db.state.a_timecode() = db.inputs.a_timecode() * pxr::SdfTimeCode(0.0);
            db.state.a_timecode_array.resize(0);

            db.state.a_token() = omni::fabric::kUninitializedToken;
            db.state.a_token_array.resize(0);

            db.state.a_uchar() = 0;
            db.state.a_uchar_array.resize(0);

            db.state.a_uint() = 0;
            db.state.a_uint_array.resize(0);

            db.state.a_uint64() = 0;
            db.state.a_uint64_array.resize(0);

            db.state.a_vectord_3().Set(0.0, 0.0, 0.0);
            db.state.a_vectorf_3().Set(0.0f, 0.0f, 0.0f);
            db.state.a_vectorh_3() *= 0.0;
            db.state.a_vectord_3_array.resize(0);
            db.state.a_vectorf_3_array.resize(0);
            db.state.a_vectorh_3_array.resize(0);
        }

        // OM-41949 Not building when referencing certain types of state bundle members
        auto runtimeInt3Array = db.state.a_bundle().attributeByName(db.stringToToken("inputs:a_int_3_array"));
        if (runtimeInt3Array.isValid())
        {
            // Artificial path to do something the compiler can't elide
            auto extractedValue = runtimeInt3Array.getCpu<int[][3]>();
            if (extractedValue.size() > 0)
            {
                return true;
            }
        }

        return true;
    }
};

REGISTER_OGN_NODE()

} // namespace test
} // namespace graph
} // namespace omni
