/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
***************************************************************************/
#if defined(GLM_EXPORT_ALEMBIC)

#pragma once

#include <glmString.h>
#include <glmArray.h>
#include <glmVector3.h>
#include <glmPODArray.h>

#include "glmCrowdIOAPI.h"
#include "glmAlembic.h"

namespace glm
{
	namespace crowdio
	{
		// Defines an alembic polymesh. It's a compound of samples that share the same number of vertices, indices, polygons, and count of vertices per face.
		// THERE SHOULD BE ONE AlembicFurCurves PER FUR MESH ASSET to keep a single parent transform correctly named at export 
		class GLM_CROWDIO_API AlembicFurCurves
		{
		public:

			// Inner class that stores the vertices, widths and uvs for a sample of polymesh
			class GLM_CROWDIO_API Sample
			{
			public:
				Sample(unsigned int vertexTotalCount); // uvCount == vertexCount, width == vertexCount

				virtual ~Sample();
				
				const ::Alembic::AbcGeom::Abc::float32_t* getVertices() const;
				const ::Alembic::AbcGeom::Abc::float32_t* getWidths() const;
				const ::Alembic::AbcGeom::Abc::float32_t* getUVs() const;

				::Alembic::AbcGeom::Abc::float32_t* touchVertices();
				::Alembic::AbcGeom::Abc::float32_t* touchWidths();
				::Alembic::AbcGeom::Abc::float32_t* touchUVs();

				void setGlobalMatrix(const ::Alembic::AbcGeom::Abc::M44d &mat);
				::Alembic::AbcGeom::Abc::M44d getGlobalMatrix() const;

				glm::PODArray<float>& touchFloatUserDataValues();
				glm::Array<Vector3>& touchVectorUserDataValues();
				void release();

			private:

				::Alembic::AbcGeom::Abc::float32_t* _vertices;
				::Alembic::AbcGeom::Abc::float32_t* _widths;
				::Alembic::AbcGeom::Abc::float32_t* _uvs;

				/// The global transformation matrix
				::Alembic::AbcGeom::Abc::M44d _globalMatrix;
				/// Userdata
				glm::PODArray<float> _floatUserDataValues;
				glm::Array<Vector3> _vectorUserDataValues;
			};

			//************************************************************
			/*! @name Constructor & Destructor
			*/ //*********************************************************
			//@{
			/**
			* \brief Constructor
			*/
			AlembicFurCurves(const GlmString& fullPathName, const GlmString& shadingGroupNames,
				const glm::Array<glm::GlmString>& floatUserDataNames, const glm::Array<glm::GlmString>& vectorUserDataNames,
				unsigned int curveCount, uint32_t* verticesPerCurve, uint8_t degree);

			/**
			* \brief Destructor
			*/
			virtual ~AlembicFurCurves();
			//@}

			//************************************************************
			/*! @name Accessors
			*/ //*********************************************************
			//@{
			//const GlmString& getName() const;

			unsigned int getNbSamples() const;
			void addNewSample();
			Sample* touchSampleAt(unsigned int iSample);
			Sample* getLastSample();

			unsigned int getNbCurves() const { return _nbCurves; }
			unsigned int getNbTotalVertices() const { return _nbTotalVertices; }

			const ::Alembic::AbcGeom::Abc::int32_t* getVerticesPerCurve() const;
			
			//************************************************************
			/*! @name Data Members
			*/ //*********************************************************
			//@{

			// such as /body/top/hair/short_hair short_hair being the mesh
			GlmString _fullPathName;

			GlmString _shadingGroupNames;

			::Alembic::AbcGeom::Abc::int32_t* _verticesPerCurve;

			glm::Array<glm::GlmString> _floatUserDataNames;
			glm::Array<glm::GlmString> _vectorUserDataNames;
			
			unsigned int _nbCurves;
			unsigned int _nbTotalVertices; // this is an helper, could be deduced from _verticesPerCurve

			glm::PODArray<Sample*> _samples;

			int _currentSampleIndex;

			uint8_t _curvesDegree; // 1 -> linear, 3 -> cubic, anything in [1-255]
			//@}
		};
	}
}

#endif // GLM_EXPORT_ALEMBIC
