// Declaration of the class that implements CryExportCgf Maya plugin command
#pragma once
#include "CmdExportCryFile.h"
#include "MayaCryBoneUtil.h"

class CMayaCryMeshUtil;

// Export CGF command
class CCmdExportCgf :
	public CCmdExportCryFile
{
public:
	CCmdExportCgf(void);
	~CCmdExportCgf(void);

	virtual MStatus	doIt ( const MArgList& );					
	
	static void*	creator()
	{
		return new CCmdExportCgf();
	}

	static MSyntax newSyntax();

protected:
	// flags used in the syntax of this command
	//static const char;

	// Exports the given shaders as a material chunk
	// returns this chunk's id
	// throws an error if fails to write the chunk for some reason
	unsigned exportMaterial (const MObject& objShader);

	// returns the given material chunk id;
	// exports the material if it's met first time.
	// returns -1 if the material cannot be exported
	int getMaterialChunkId (const MObject& objShader);

	// Exports the multimaterial, which is a set of materials.
	// returns the given multimaterial chunk id.
	int exportMultiMaterial (const MObjectSet& setMtls);

	// returns the 0-based index of the given material in the file
	int getMaterialIndex (const MObject& objShader);

	// returns the 0-based index of the given material in the fiel,
	// given already saved material chunk id
	int getMaterialIndexByChunkId (int nChunkId);

	// exports the mesh chunk MESH_CHUNK_DESC
	// exports the bone information, if present
	// returns the chunk id for the shape
	int exportShape (const MDagPath& pathMesh);

	// exports the light chunk LIGHT_CHUNK_DESC
	// returns the chunk id for the light
	int exportLight (const MDagPath& pathLight);

	// exports the helper chunk HELPER_CHUNK_DESC
	// returns the chunk id for the helper
	int exportHelper (const MDagPath& pathHelper);


	// this is the structure used to prepare nodes: for each node, an instance of this structure is associated
	struct NodePreExportInfo
	{
		NodePreExportInfo (int _nObjectId, int _nChunkId):
			nObjectId (_nObjectId), nChunkId(_nChunkId)
			{
			}
		int nObjectId, nChunkId;
	};

	// exports the node into NODE_CHUNK_DESC_VERSION. Uses the info collected by the preparation phase of node export:
	// nodes are exported in 2 passes: prepare and export. During export, the whole information 
	// about all nodes is necessary, because nodes may refer to each other
	void exportNode (MDagPath pathNode, const NodePreExportInfo& NodeInfo);

	// preapres the node for export: adds it to the array of exoprted nodes
	// nodes are exported in 2 passes: prepare and export. During export, the whole information 
	// about all nodes is necessary, because nodes may refer to each other
	void prepareNodeForExport (MDagPath pathNode, int nNodeObjectId);

	// exports all nodes collected during preparation phase
	// nodes are exported in 2 passes: prepare and export. During export, the whole information 
	// about all nodes is necessary, because nodes may refer to each other
	void exportAllNodes();

	// finds the node parent, if any, or returns -1
	int getNodeParentChunkId (const MDagPath& pathNode);

	// finds the node children and puts them all into the array
	void getNodeChildrenChunkIds (const MDagPath& pathNode, std::vector<int>& arrChildren);

	// finds the node chunk id
	int getNodeChunkId (const MDagPath& pathNode);

	// prepares and exports material chunks out of the given geometry
	// modifies the geometry face material references so that they point to the actual material chunks
	unsigned prepareMaterials (CMayaCryMeshUtil& Mesh);

	// exports the bone name list chunk, using the bone info collected in the m_Bones
	void exportBoneNameList ();

	// exports the bone animation chunk: miscellaneous information about the bones
	void exportBoneAnim ();

	// exports the subchunk containing link/weight information for all vertices in the geometry
	void exportMeshBoneInfoSubchunk (const MDagPath& pathShape, CMayaCryMeshUtil& CryMesh);

	// exports the subchunk containing colors for vertices
	void exportVertColInfoSubchunk (const MDagPath& pathShape, CMayaCryMeshUtil& CryMesh);

	// exports the ChunkType_BoneLightBinding chunk 
	int exportLightBinding();

	// normalize and export the influences that are big enough
	//void exportCryLinks (const MFloatArray& arrWeights, const std::vector<int>& arrBoneMap);

	// puts the indices of significant link weights into the given array
	// returns the calculated sum of the "significant" links
	float getSignificantLinks  (const MFloatArray& arrWeights, std::vector<unsigned>& arrSignificantLinkIndices);

	// prepares the array of shapes for export (fills the m_setShapes in)
	void prepareObjectsToExport(const MSelectionList& listSelection);

	// adds the lights attached to the bones
	void prepareAttachedLightsToExport ();

	// prepares the given light for export - adds it to the light list
	void prepareLightToExport (const MDagPath& pathDagNode	);

	// prepares the array of SBoneLightBind for exporting, when the bones are filled in (m_Bones)
	// and the light has assigned chunk ids
	void prepareLightBindingInfo (const MDagPath& pathLight, unsigned nChunkId);

	// determines the shapes that this node (Bone) may influence and adds them to the set of shapes to export
	bool prepareConnectedFleshToExport (const MDagPath& pathDagNode);

	void prepareNonShapeToExport (const MDagPath& pathDagNode);

	// prepares the m_Bones utility object: pushes all bones influencing shapes here
	void initBones();

	// logs the exported shape names
	void dumpExportedObjects();

	// converts texture names, if needed, to CryEngine format
	void convertTextureNames (MTL_CHUNK_DESC_EXPORTER& desc);
	
	// converts the given texture name from tga to dds extension
	void convertTextureTGAtoDDS (char* szName, int nMap);
protected: // attributes
	// exported materials - MObject->chunk id map; -1 is instead of chunk id if the material failed to export
	typedef std::pair<MObject,int> ExportMtlEntry;
	typedef std::vector<ExportMtlEntry> ExportMtlMap;
	ExportMtlMap m_arrExportMtlMap;

	// material ids (chunk ids currently) for nodes
	typedef std::map<MDagPath, unsigned, MDagPathOrder> NodeMtlMap;
	NodeMtlMap m_mapNodeMtl;

	// indicates if the exported shape(s) will have bone info
	bool m_hasBoneInfo;

	// the information about the bone hierarchy
	// this is exported upon export of the shape info
	CMayaCryBoneUtil m_Bones;

	// minimal weight of an influence to export
	float m_fMinLinkWeight;

	// the array of shapes to export
	MDagPathSet m_setShapes;

	// the array of lights to export
	MDagPathSet m_setLights;

	// the array of helpers to export
	MDagPathSet m_setHelpers;

	// the array of light bindings to bones; it's created during exporting of the lights.
	std::vector<SBoneLightBind> m_arrLightBinding;

	// the map of nodes to export: the preparation stage of node export gathers this map,
	// and the exporting stage exports all the nodes.
	typedef std::map<MDagPath, NodePreExportInfo, MDagPathOrder> NodePreExportMap;
	NodePreExportMap m_mapNodePreExportInfo;
};
