#include "MAXProxyHeaders.hpp"

//
//############################################################################
//##########################    MAXVertex    ###########################
//############################################################################
//

MemoryBlock*
	MAXVertex::AllocatedMemory = NULL;
MAXVertex::ClassData*
	MAXVertex::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::InitializeClass()
{
	Verify(!AllocatedMemory);
	AllocatedMemory =
		new MemoryBlock(
			sizeof(MAXVertex),
			10,
			10,
			"MAXVertex"
		);
	Register_Object(AllocatedMemory);

	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			MAXVertexClassID,
			"MAXVertex",
			VertexProxy::DefaultData
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;

	Unregister_Object(AllocatedMemory);
	delete AllocatedMemory;
	AllocatedMemory = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::Destroy()
{
	Check_Object(this);
	Verify(referenceCount == 1);
	DetachReference();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MAXVertex::MAXVertex(
	MAXPolygonMesh *mesh,
	int index,
	int texture_index,
	Point3 *vertex,
	int face_index
):
	Proxies::VertexProxy(DefaultData, mesh),
	vertexIndex(index),
	vertexTextureIndex(texture_index),
	faceIndex(face_index)
{
	Check_Pointer(this);
	Check_Object(mesh);
	Check_Object(this);
	proxiedVertex.x = vertex->x;
	proxiedVertex.y = vertex->y;
	proxiedVertex.z = vertex->z;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MAXVertex::~MAXVertex()
{
	Check_Object(this);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::TestInstance() const
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::GetPosition(Point3D *position)
{
	Check_Object(this);
	Check_Pointer(position);
	//
	//---------------------------------
	// Copy the data to the destination
	//---------------------------------
	//
	Point3D offset_translation;
	offset_translation=ConvertMaxToMW(proxiedVertex);
	MAXPolygonMesh *mesh = GetPolygonMeshProxy();
	position->Multiply(offset_translation, mesh->meshToPivot);

/*
	position->x = static_cast<Scalar>(proxiedVertex.x);
	position->y = static_cast<Scalar>(proxiedVertex.z);
	position->z = -static_cast<Scalar>(proxiedVertex.y);
*/
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::SetPosition(const Point3D &position)
{
	Check_Object(this);
	Check_Object(&position);

	proxiedVertex.x = static_cast<float>(position.x);
	proxiedVertex.y = static_cast<float>(position.z);
	proxiedVertex.z = -static_cast<float>(position.y);

}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MAXVertex::GetColor(RGBAColor *color)
{
	Check_Object(this);
	Check_Object(color);
	
	MAXPolygonMesh*mesh_proxy = GetPolygonMeshProxy();
	Check_Pointer(mesh_proxy);

	if (vertexIndex < mesh_proxy->GetnumCVerts())
	{
		color->red   = mesh_proxy->GetvertColor(vertexIndex)->x;
		color->green  = mesh_proxy->GetvertColor(vertexIndex)->y;
		color->blue   = mesh_proxy->GetvertColor(vertexIndex)->z;
	}
	else
	{
		color->red    = 1.0;
		color->green  = 1.0;
		color->blue   = 1.0;
	}
	color->alpha = 1.0f;

	return true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::SetColor(const RGBAColor& color)
{
	Check_Object(this);
	Check_Object(&color);

	MAXPolygonMesh*mesh_proxy = GetPolygonMeshProxy();
	Check_Pointer(mesh_proxy);

	VertColor vertCol = *mesh_proxy->GetvertColor(vertexIndex);

	vertCol.x = color.red;
	vertCol.y = color.green;
	vertCol.z = color.blue;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MAXVertex::GetNormal(Normal3D *normal)
{
	Check_Object(this);
	Check_Pointer(normal);

	MAXPolygonMesh*mesh_proxy = GetPolygonMeshProxy();
	Check_Pointer(mesh_proxy);
	//
	//---------------
	// Get the normal
	//---------------
	//
	Point3 vn;
	if (mesh_proxy->GetVertexGroup(vertexIndex))
		vn = mesh_proxy->GetVertexNormal(vertexIndex);
	else
		vn = mesh_proxy->GetFaceNormal(faceIndex);

	Vector3D long_norm;
	long_norm = ConvertMaxToMW(vn);
	Scalar len = long_norm.GetLength();
	if (Small_Enough(len))
	{
		if(!mesh_proxy->GetSceneProxy()->notifiedOfError)
		{
			mesh_proxy->GetSceneProxy()->notifiedOfError = true;
			Interface *ip = mesh_proxy->GetSceneProxy()->GetInterface();
			MessageBox(ip->GetMAXHWnd(),_T("Equal Vertex Values! Try Welding"),_T("Vertex Error."),MB_OK);
		}
		return false;
	}

	Normal3D norm;
	len = 1.0f / len;
	norm.x = len * long_norm.x;
	norm.y = len * long_norm.y;
	norm.z = len * long_norm.z;
	normal->Multiply(norm, mesh_proxy->meshToPivot);

	return true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::SetNormal(const Normal3D &normal)
{
	Check_Object(this);
	Check_Object(&normal);
	MAXPolygonMesh*mesh_proxy = GetPolygonMeshProxy();
	Check_Pointer(mesh_proxy);
	//
	//---------------
	// Set the normal
	//---------------
	//
	Point3 norm;

	norm.x = static_cast<float>(normal.x);
	norm.y = static_cast<float>(normal.z);
	norm.z = -static_cast<float>(normal.y);

	mesh_proxy->SetNormal(vertexIndex, norm);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
	MAXVertex::GetUVs(Stuff::DynamicArrayOf<Stuff::Vector2DOf<Stuff::Scalar> > *vector)
{
	Check_Object(this);
	Check_Object(vector);

	MAXPolygonMesh*mesh_proxy = GetPolygonMeshProxy();
	Check_Pointer(mesh_proxy);
	int number_uvs = mesh_proxy->GetNumberTextureMaps(faceIndex);

	Verify(number_uvs <= 2);

	if (mesh_proxy->GetnumTVerts()<=0)
	{
		return false;
	}
	UVVert tvert = mesh_proxy->GetTVert(vertexTextureIndex);

	if (number_uvs <= 0)
	{
		vector->SetLength(1);
		(*vector)[0].x = tvert.x;
		(*vector)[0].y = 1.0f - tvert.y;
	}
	else
	{
		vector->SetLength(number_uvs);
		for (int i=0;i<number_uvs;i++)
		{
			int type = mesh_proxy->GetUVTypeOfMap(i,faceIndex);
			if (type == UVWSRC_EXPLICIT)
			{
				(*vector)[i].x = tvert.x;
				(*vector)[i].y = 1.0f - tvert.y;
			}
			else if (type == UVWSRC_EXPLICIT2)
			{
				Verify (mesh_proxy->GetNumVertCol() > 0);
				(*vector)[i].x = mesh_proxy->GetvertColor(vertexIndex)->x;
				(*vector)[i].y = 1.0f - mesh_proxy->GetvertColor(vertexIndex)->y;
			} 
			else
			{
				(*vector)[i].x = tvert.x;
				(*vector)[i].y = 1.0f - tvert.y;
			}
		}
	}
	return true;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MAXVertex::SetUVs(const Stuff::DynamicArrayOf<Stuff::Vector2DOf<Stuff::Scalar> > &vector)
{
	Check_Object(this);
	Check_Object(&vector);
	
	MAXPolygonMesh*mesh_proxy = GetPolygonMeshProxy();
	Check_Pointer(mesh_proxy);
	
	UVVert tvert;
	tvert.x = vector[0].x;
	tvert.y = vector[0].y;

	mesh_proxy->SetTVert(vertexTextureIndex,tvert);
}