/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A. - All Rights Reserved.                        *
*                                                                          *
***************************************************************************/
#pragma once

#include <glmCrowdIOAPI.h>
#include "glmAssetAssociations.h"
#include "glmAssetManagementUtils.h"
#include "glmSimulationCacheVisualFeedbackArray.h"

#include <glmGolaemCharacterDeclarations.h> // GolaemCharacter declarations

#define MIRROR_ON_ATTR_NAME "glm_LayoutMirrorGeometryOn"
#define MIRROR_CENTER_POS_ATTR_NAME "glm_LayoutMirrorGeometryCenterPos"
#define MIRROR_CENTER_ORI_ATTR_NAME "glm_LayoutMirrorGeometryCenterOri"

#define REPLACE_LOD_MIN_DISTANCES_ON_ATTR_NAME "glm_LayoutReplaceLODMinDistancesOn"
#define REPLACE_LOD_MAX_DISTANCES_ON_ATTR_NAME "glm_LayoutReplaceLODMaxDistancesOn"
#define REPLACE_LOD_MIN_DISTANCES_ATTR_NAME "glm_LayoutReplaceLODMinDistances"
#define REPLACE_LOD_MAX_DISTANCES_ATTR_NAME "glm_LayoutReplaceLODMaxDistances"

namespace glm
{
    namespace crowdio
    {
        //-------------------------------------------------------------------------
        // Predeclarations
        //-------------------------------------------------------------------------
        struct GlmSimulationData_v0;
        struct GlmFrameData_v0;
        struct GlmLayoutNode_v1;
        class glmHistoryRuntimeStructure;
        class CachedSimulation;
        struct GlmFrameToLoad_v0;
        struct GlmAttribute_v1;

        //-------------------------------------------------------------------------
        // History Transformation Types
        //-------------------------------------------------------------------------
        struct SimulationCacheTransformType
        {
        public:
            enum Value
            {
                Noop,
                Rotate,
                Scale,
                Translate,
                Duplicate,
                Kill,
                Unkill,
                SetMeshAssets,
                Expand,
                FrameOffset,
                FrameWarp,
                ScaleRange,
                SnapTo,
                SetShaderAttribute,
                ReplaceShader,
                GroundAdaptation,
                Posture,
                Rig,
                Note,
                SetRenderingType,
                AddRemoveMeshAssets,
                TrajectoryVectorField,
                Group,
                FaceTo,
                LookAt,
                SetFrame,
                SetGeometryFile,
                BlindData,
                SetAttribute,
				MirrorGeometry,
				ReplaceLODDistances,
				EditTrajectory,
                PlayMotion,
                CreateEntity,
                OpsCount //allows to count the number of transforms types
            };
        };

        // return a string containing the transform type name
        extern const char* getSimulationCacheTransformTypeString(SimulationCacheTransformType::Value type);

        // Function pointers on simulation cache transform operation on input frame selection
        typedef void (*CacheFrameSelectionFunctionPointer)(const GlmLayoutNode_v1* currentNode, size_t currentNodeExecutionOrderIndex, const glmHistoryRuntimeStructure* historyRuntime, int64_t entityID, const glm::Time inputFrameIndex, glm::Time& outputFrameIndex);
        extern GLM_CROWDIO_API CacheFrameSelectionFunctionPointer cacheFrameSelectionPointers[];

        // Function pointers on simulation cache transform operation on sim data
        typedef void (*CacheSimulationDataTransformationFunctionPointer)(const GlmLayoutNode_v1* currentNode, int currentNodeIndex, size_t currentNodeExecutionOrderIndex, CachedSimulation& cachedSimulation, glmHistoryRuntimeStructure* historyRuntime, const GlmSimulationData_v0* srcSimData, GlmSimulationData_v0* dstSimData);
        extern GLM_CROWDIO_API CacheSimulationDataTransformationFunctionPointer cacheSimDataTransformationPointers[];

        // Function pointers on simulation cache transform operation on frame data
        typedef void (*CacheFrameDataTransformationFunctionPointer)(const GlmLayoutNode_v1* currentNode, int currentNodeIndex, size_t currentNodeExecutionOrderIndex, CachedSimulation& cachedSimulation, size_t historyIndex, int currentFrameIndex, GlmSimulationData_v0* dstSimData, GlmFrameData_v0* dstFrameData, SimulationCacheVisualFeedbackArray* visualFeedbackArray);
        extern GLM_CROWDIO_API CacheFrameDataTransformationFunctionPointer cacheFrameDataTransformationPointers[];

        // Function pointers on simulation cache asset association
        typedef void (*CacheAssetAssociationFunctionPointer)(const GlmLayoutNode_v1* currentNode, int currentNodeIndex, size_t currentNodeExecutionOrderIndex, CachedSimulation& cachedSimulation, size_t historyIndex, glm::Time currentTime, const GlmSimulationData_v0* srcSimData, const GlmSimulationData_v0* dstSimData, Array<AssetOverride>& assetOverrides, Array<ShaderOverrides>& shaderOverrides, ShaderNameReplacement& shaderNameReplacements);
        extern GLM_CROWDIO_API CacheAssetAssociationFunctionPointer cacheAssetAssociationPointers[];

        // Attribute interpolations
		int32_t extern GLM_CROWDIO_API evaluateInt32AttributeValue(const GlmAttribute_v1& attribute, glm::Time currentFrameIndex, int currentValueIndex, short mode);
        float extern GLM_CROWDIO_API evaluateFloatAttributeValue(const GlmAttribute_v1& attribute, glm::Time currentFrameIndex, int currentValueIndex, short mode);
        Vector3 extern GLM_CROWDIO_API evaluateVec3AttributeValue(const GlmAttribute_v1& attribute, glm::Time currentFrameIndex, int currentValueIndex, short mode);

        //IK chain info from the mapping
        void extern GLM_CROWDIO_API buildIKChainsList(const GenericSpecificConverterMapping* entityConverterMapping, glm::Array<GenericSpecificConverterBone>& outIkChains, glm::Array<glm::GlmString>& outIkChainsNames, glm::Array<int>& outIkChainParents, glm::Array<bool>& outIkChainHasFootLock);

        //Entity transforms extraction from the pelvis transforms
        void extern GLM_CROWDIO_API computeEntityPositionFromZupPelvis(Vector3& outEntityPosition, const Vector3& inPelvisPosition, const Quaternion& inPelvisOrientation, const Vector3& worldUpVector, const float entityScale, const float rootHeightRatio, const float rootHeightUnscaled);

		//local helpers, not exported
		bool extern isFrameInKeyFramesRange(const glm::Time& currentFrameIndex, const GlmAttribute_v1& attribute);
		int64_t extern getNoiseId(int64_t dstEntityId, size_t currentNodeExecutionOrderIndex, const glmHistoryRuntimeStructure* historyRuntime);
		float extern sampleTextureRGBA(Vector4& outMapvalue, unsigned char* rawMap, unsigned mapWidth, unsigned mapHeight, const Vector2& uvCoordinates);

    } // namespace crowdio
} // namespace glm
