#pragma once
#include <d3d9.h>
#include <d3dx9.h>
#include "XFileLoader.h"
#include "Direct3DStructures.h"
#include "XFile.h"
#include "Animation.h"

#define ReleaseCOM(x) { if(x!=NULL) x->Release(); x=NULL; }

const int MAX_OBJECT_EFFECTS = 10;

class MeshObject : XFileLoader {

private:
	int leftLegTight = 1054, rightLegTight = 1044, leftLegTightEnd = 1131, leftLegKnee = 1090, leftLegKneeEnd = 1064,  rightLegKnee = 1009, leftLegAnkle = 1787, rightLegAnkle = 1683;
	float tightRadius, calfRadius;
	int leftForearm = 943, rightForearm = 903, leftForearmEnd = 972, leftElbow = 953, leftElbowEnd = 956, rightElbow = 926, leftHand = 320, rightHand = 512;
	float forearmRadius, armRadius;

public:
	IDirect3DDevice9 *pDevice;

	DWORD dwNumMaterials;
	ID3DXMesh *m_Mesh;
	LPDIRECT3DTEXTURE9 *pMeshTextures;
	D3DMATERIAL9 *pMeshMaterials;

	ID3DXEffect *pEffect[MAX_OBJECT_EFFECTS];
	TCHAR *pTechniqueName[MAX_OBJECT_EFFECTS];

	D3DXVECTOR4 Light[MAX_OBJECT_EFFECTS];

	D3DXMATRIX matWorld;

	cAnimationSet *pAnimationSets;
	DWORD NumAnimationSets;

	D3DXFRAME_EX *pSkinFrame;

	LPD3DXSKININFO SkinInfo;

	D3DXMATRIX **ppFrameMatrix;
	D3DXMATRIX *pBoneMatrix;
	D3DXMESHDATA MeshData;

	ID3DXMesh *pObjMesh;

	ID3DXMesh *ppMesh;
	D3DXVECTOR3 leftLegTight_v3, rightLegTight_v3, leftLegKnee_v3, rightLegKnee_v3, leftLegAnkle_v3, rightLegAnkle_v3;
	D3DXVECTOR3 leftForearm_v3, rightForearm_v3, leftElbow_v3, rightElbow_v3, leftHand_v3, rightHand_v3;


private:
	//Create new SkinFrame equal to this
	D3DXFRAME_EX* CloneSkinFrame(D3DXFRAME_EX *originalFrame);

	//Create new cAnimationSet equal to this
	cAnimationSet* CloneAnimationSet(cAnimationSet *originalAnimationSet, D3DXFRAME_EX *Frame);

	//Create new cAnimation equal to this
	cAnimation* CloneAnimation(cAnimation *originalAnimation, cAnimation *previousAnimation, D3DXFRAME_EX *Frame);

public:

	MeshObject(IDirect3DDevice9 *pD3DDevice)
	{
		D3DXMatrixIdentity(&matWorld);
		pDevice = pD3DDevice;
		dwNumMaterials = NULL;
		m_Mesh = NULL;
		pMeshTextures = NULL;
		pMeshMaterials = NULL;
		pEffect[MAX_OBJECT_EFFECTS] = NULL;
		pTechniqueName[MAX_OBJECT_EFFECTS] = NULL;
		SkinInfo = NULL;
		pSkinFrame = NULL;
		ppFrameMatrix = NULL;
		pBoneMatrix = NULL;
		pObjMesh = NULL;
		pAnimationSets = NULL;
		NumAnimationSets = NULL;
		ppMesh = NULL;
		pObjMesh = NULL;
	};

	bool LoadSkinMeshFromFile(const char* filename);

	bool ParseObject(ID3DXFileData *pDataObj, ID3DXFileData *pParentDataObj, D3DXFRAME_EX **frd, bool ref);

	HRESULT LoadMeshWithSkin(IDirect3DDevice9 *pDevice, ID3DXFileData *pDataObj, DWORD LoadFlags);

	bool ParseChild(ID3DXFileData *pDataObj, D3DXFRAME_EX **frd, bool ref);

	//Find frame by name
	D3DXFRAME_EX * FindDXFrame(const char *FrameName, D3DXFRAME_EX *Frame);

	//Set transformation matrix for frame
	void SetMatrix(D3DXMATRIX *matTransformation, D3DXFRAME_EX *Frame);

	//Set new matrix for matWorld
	void SetWorldPos(D3DXMATRIX* matrix);

	//Get position of the world
	D3DXMATRIX* GetWorldPos();

	//Update mesh 
	HRESULT UpdateMesh();

	//Set new posision of  MeshObject
	void SkinnedMeshPositioning();

	//Update TransformationMatrix of every bone which is used in animation
	void UpdateSkinAnimation(DWORD Time);

	//Compare bones and frames
	void Map(D3DXFRAME_EX *RootFrame);

	//Draw animated model
	void DrawModel();

	//Create new MeshObject equal to this
	MeshObject* CloneMeshObject(const char*);

	//Get points for legs
	D3DXVECTOR3* GetPointsForLegs();

	//Get points for arms
	D3DXVECTOR3* GetPointsForArms();

	//Set points for legs
	void SetLeftTightPoints(int* points);
	void SetRightTightPoints(int* points);
	void SetLeftCalfPoints(int* points);
	void SetRightCalfPoints(int* points);

	//Get radius of legs
	float GetTightRadius();
	float GetCalfRadius();

	//Get radius of arms
	float GetForearmRadius();
	float GetArmRadius();


};

