#include "xLoader.h"
#include <string>
#include <strstream>

using namespace std;

namespace CBK
{
	namespace Shapes
	{
		xLoader::xLoader(const std::string& fileName, const MeshParam& params) : Mesh(params, fileName)
		{
			load(fileName, params);
		}

		xLoader::~xLoader(void)
		{
		}

		string xLoader::materialToString(const D3DMATERIAL9& material)
		{
			strstream myBuff;

			myBuff << material.Ambient.r;
			myBuff << " ";
			myBuff << material.Ambient.g;
			myBuff << " ";
			myBuff << material.Ambient.b;
			myBuff << " ";
			myBuff << material.Ambient.a;
			myBuff << " ";

			myBuff << material.Diffuse.r;
			myBuff << " ";
			myBuff << material.Diffuse.g;
			myBuff << " ";
			myBuff << material.Diffuse.b;
			myBuff << " ";
			myBuff << material.Diffuse.a;
			myBuff << " ";

			myBuff << material.Specular.r;
			myBuff << " ";
			myBuff << material.Specular.g;
			myBuff << " ";
			myBuff << material.Specular.b;
			myBuff << " ";
			myBuff << material.Specular.a;
			myBuff << " ";

			myBuff << material.Emissive.r;
			myBuff << " ";
			myBuff << material.Emissive.g;
			myBuff << " ";
			myBuff << material.Emissive.b;
			myBuff << " ";
			myBuff << material.Emissive.a;
			myBuff << " ";

			myBuff << material.Power;
			myBuff.write("\0", 1);

			return myBuff.str();
		}

		item& xLoader::load(const std::string& fileName, const MeshParam& params)
		{
			if (params.device != 0)
				_device = params.device;
			ID3DXBuffer* adjBuffer  = 0;
			ID3DXBuffer* mtrlBuffer = 0;
			DWORD        numMtrls   = 0;
			
			D3DXLoadMeshFromX(fileName.c_str(), D3DXMESH_MANAGED, _device, &adjBuffer, &mtrlBuffer, 0, &numMtrls, &_mesh);
			_subsets = numMtrls;

			if( mtrlBuffer != 0 && numMtrls != 0 )
			{
				D3DXMATERIAL* mtrls = (D3DXMATERIAL*)mtrlBuffer->GetBufferPointer();
				_materials.resize(numMtrls);
				_textures.resize(numMtrls);

				for(register DWORD i = 0; i < numMtrls; i++)
				{
					// the MatD3D property doesn't have an ambient value set
					// when its loaded, so set it now:
					mtrls[i].MatD3D.Ambient = mtrls[i].MatD3D.Diffuse;

					// save the ith material
					setMaterial(materialToString(mtrls[i].MatD3D), i);

					// check if the ith material has an associative texture
					if (mtrls[i].pTextureFilename != 0)
						setTexture(mtrls[i].pTextureFilename, i);
					else
						setTexture("", i);
				}
			}
			d3d::Release<ID3DXBuffer*>(mtrlBuffer);

			_mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjBuffer->GetBufferPointer(), 0, 0, 0);
			d3d::Release<ID3DXBuffer*>(adjBuffer);

			return *this;
		}
	}
}