/*	Golaem Crowd API - v1.00 - Copyright (C) Golaem SA.  All Rights Reserved.

	QUICK NOTES:
	Primarily of interest to pipeline developers to integrate Golaem Crowd simulation cache

	Brief documentation under "DOCUMENTATION" below.

	Revision 1.00 (2018-09-01) release notes:
	- Completely rebranded API, now integrated in CrowdIO. GlmSimulationData and GlmFrameData are almost unchanged from previous version, while GlmHistory is completelly redone from scratch to allow a new nodal UI

	Revision 0.10 (2015-03-12) release notes:
	- Separated declarations and definition of function in 2 separate files
	Revision 0.00 (2015-03-12) release notes:
	- Functions and structures for creation, read/write and destruction of Golaem Simulation Caches

*/

#ifndef GLM_SIMULATIONCACHECOMMON_H
#define GLM_SIMULATIONCACHECOMMON_H

#include "stdint.h"
#include "stdio.h"

#include <glmCrowdIOAPI.h>

// DOCUMENTATION
//
// ===========================================================================
// Simulation Cache
//
// .gscs contains a SimulationData struct, simulation common data for all frames
// .gscf contains a FrameData struct, frame-specific data
//
// Basic read frames-data usage:
//		GlmSimulationCacheStatus status;
//		GlmSimulationData* simulationData;
//		status = createAndReadSimulationData(&simulationData, gscsFileName);
//		if (status != GSC_SUCCESS) ...
//		GlmFrameData* frameData;
//		createFrameData(&frameData, simulationData);
//		status = readFrameData(frameData, simulationData, gscfFileName);
//		if (status != GSC_SUCCESS) ...
//		...
//		status = readFrameData(frameData, simulationData, gscfFileName);
//		if (status != GSC_SUCCESS) ...
//		...
//		destroyFrameData(&frameData);
//		destroySimulationData(&simulationData);
//

// ===========================================================================
// Simulation cache current version
//
// version 0x00 : original version
// version 0x01 : Added Sns 4th value, set to 1 for backward compatibility
// version 0x02 : split ppattributes per type, generate cloth runtime data accesss helpers (vertices and indices offset)
// version 0x03 : Added evalMode, set to 0 for backward compatibility
// version 0x04 : Added enable/disable uint8_t mask for emitters
// version 0x05 : Added asset associations info (_rngSeed: global, _characterIdx, _renderingTypeIdx: per entity) and _framerate: global
// version 0x06 : Added multiple rng seeds to be able to merge caches
// version 0x07 : GeoData is allocated by default
// version 0x08 : Removed entity radius and height, added entity type shape extents
// version 0x09 : Added static ppAttributes in simData, changed ppAttributes max count in frameData (was an uint8: max 256 ppAttributes)
#define GSC_VERSION 0x09

//////////////////////////////////////////////////////////////////////////////
//
// Simulation Cache API
//
namespace glm
{
    namespace crowdio
    {
        // Trajectory operation parameters -------------------------------------------

        typedef struct GlmTrajectory_Smooth_v0
        {
            int _iterationCount;
            float _frontBackRatio;
            float _components[3];
        } GlmTrajectory_Smooth;

        typedef struct GlmTrajectory_VectorField_v0
        {
            char _vectorFieldName[256];
            float _angularLimit;
            float _angularBoost;
            int _referenceFrame;
        } GlmTrajectory_VectorField;

        typedef struct GlmTrajectory_Avoidance_v0
        {
            float _frontDistance;
            float _sideDistance;
            int _iterationCount;
            float _iterationStrength;
        } GlmTrajectory_Avoidance;

        typedef struct GlmTrajectory_CurveEdit_v0
        {
            int _steps;
        } GlmTrajectory_CurveEdit;

        typedef struct GlmTrajectory_Mode_v0
        {
            int _mode;
        } GlmTrajectory_Mode;

        // Simulation cache status codes----------------------------------------------
        typedef enum
        {
            GSC_SUCCESS,
            GSC_UNKNOWN_ERROR, //no details can be given on the error
			GSC_OPENING,                                   // is being opened (process not finished)
			GSC_FILE_OPEN_FAILED,                          // failed to open
            GSC_FILE_MAGIC_NUMBER_ERROR,                   // file header does not begin by 0x65CF or 0x65CF, this is not a Golaem Simulation Cache
            GSC_FILE_VERSION_ERROR,                        // incorrect version, could be a newer version of the Golaem Simulation Cache
            GSC_FILE_FORMAT_ERROR,                         // incorrect format, could be a newer version of the Golaem Simulation Cache
            GSC_SIMULATION_FILE_DOES_NOT_MATCH,            // used Golaem Simulation Cache simulation file does not match this frame file
			GSC_SIMULATION_FRAME_NOT_IN_CACHE,             // used when no frame could be found in cache
			GSC_SIMULATION_NO_FRAMES_FOUND,                // used when no frame could be loaded from the cache
            GSC_FILE_POSITION_OUT_OF_MAX_BONECHAIN_LENGTH, // need to disable quantization in this case.
			GSC_END
        } GlmSimulationCacheStatus;

        // convert a simulation cache status in an error message
        extern GLM_CROWDIO_API const char* glmConvertSimulationCacheStatus(GlmSimulationCacheStatus status);

        extern GLM_CROWDIO_API int glmsprintf(char* str, int strSize, const char* format, ...);

        // Utils-------------------------------------------------
        extern GLM_CROWDIO_API int glmFindEntityInEntityIdArray(const int64_t* entityIds, size_t entityCount, int64_t entityId);
        extern GLM_CROWDIO_API void interpolateNFloats(float* value1, float* value2, float ratio, float* res, int count);

        extern GLM_CROWDIO_API int glmComputeValidFrameIndex(const char* cacheFileDir, const char* cacheName, const char* crowdFieldName, int frameIndex);

        extern GLM_CROWDIO_API float glmComputeLengthOnTrajectory(const float* points, int stride, int pointCount, int frameIndex, float fraction);

        extern GLM_CROWDIO_API void glmComputeFrameOffsetFromLength(const float* points, int stride, int pointCount, float lengthOnTrajectory, int* frameIndex, float* fraction);

        // compression interface (used in crowd_io)
        extern GLM_CROWDIO_API void glmFileWrite(const void* data, unsigned long elementSize, unsigned long count, FILE* fp);
        extern GLM_CROWDIO_API void glmFileWriteUInt16(const uint16_t* data, unsigned int count, FILE* fp);
        extern GLM_CROWDIO_API void glmFileWriteUInt32(const uint32_t* data, unsigned int count, FILE* fp);
        extern GLM_CROWDIO_API void glmFileWriteUInt64(const uint64_t* data, unsigned int count, FILE* fp);

        extern GLM_CROWDIO_API void glmFileRead(void* data, unsigned long elementSize, unsigned long count, FILE* fp);
        extern GLM_CROWDIO_API void glmFileReadUInt16(uint16_t* data, unsigned int count, FILE* fp);
        extern GLM_CROWDIO_API void glmFileReadUInt32(uint32_t* data, unsigned int count, FILE* fp);
        extern GLM_CROWDIO_API void glmFileReadUInt64(uint64_t* data, unsigned int count, FILE* fp);

        // hash tools (used in crowd_io)
        extern GLM_CROWDIO_API void glmStartHash(uint32_t* currentHashValue);
        extern GLM_CROWDIO_API void glmCumulativeHash8(uint8_t valueToHash, uint32_t* currentHashValue);
        extern GLM_CROWDIO_API void glmCumulativeHash16(uint16_t valueToHash, uint32_t* currentHashValue);
        extern GLM_CROWDIO_API void glmCumulativeHash32(uint32_t valueToHash, uint32_t* currentHashValue);
    } // namespace crowdio
} // namespace glm

#endif // GLM_SIMULATIONCACHECOMMON_H
