#include "mof/Board.hpp"
#include "mof/Camera.hpp"
#include "mof/Material.hpp"
#include "mof/private/GraphicsDeviceImpl.hpp"
#include "mof/ConsoleIO.hpp"
#include "mof/stream/Constant.hpp"

struct mof::Board::Impl{
	std::shared_ptr<mof::Texture> pTexture;
	mof::Manipulator<mof::Matrix3D>::Handler worldMatrix;
	mof::Manipulator<mof::Color4f>::Handler color;
	mof::Manipulator<mof::Rectangle<float>>::Handler textureCoordinates;
	FrameNumber m_frame;

	Impl( )
		: 
		worldMatrix(mof::makeConstantHandler(mof::Matrix3D::createIdentity())) ,
		textureCoordinates(mof::makeConstantHandler(mof::Rectangle<float>(0 , 0 , 1 , 1))) ,
		color(mof::makeConstantHandler(mof::Color4f(1 , 1 , 1))),
		m_frame(0)
	{
	}

	~Impl(){}
};



mof::Board::Board() : m_pImpl(new Impl()){
}

mof::Board::~Board(){
}
	



void mof::Board::setWorldMatrix(const mof::Manipulator<mof::Matrix3D>::Handler& handler){
	m_pImpl->worldMatrix = handler;

}

mof::Matrix3D mof::Board::getWorldMatrix() const
{
	return m_pImpl->worldMatrix->value(m_pImpl->m_frame);
}

mof::Vector3D mof::Board::getPosition() const
{
	mof::Matrix3D m = getWorldMatrix();
	return mof::Vector3D(m.at(3, 0), m.at(3, 1), m.at(3, 2) );
}



void mof::Board::setColor(const mof::Manipulator<mof::Color4f>::Handler& handler){
	m_pImpl->color = handler;
}




void mof::Board::setTextureCoordinates(const mof::Manipulator<mof::Rectangle<float>>::Handler& handler){
	m_pImpl->textureCoordinates = handler;
}

void mof::Board::setTextureCoordinates(const mof::Rectangle<float>& coordinates){
	setTextureCoordinates(mof::makeConstantHandler(coordinates));
}

void mof::Board::setTexture( const std::shared_ptr<mof::Texture>& pTexture ){
	m_pImpl->pTexture = pTexture;
}


bool mof::Board::isVisible() const{
	return true;
}

void mof::Board::update(){
	m_pImpl->m_frame++;
}


void mof::Board::draw() const{
	mof::FrameNumber frame = m_pImpl->m_frame;
	mof::Rectangle<float> textureCoordinates = m_pImpl->textureCoordinates->value(frame);
	mof::Color color = m_pImpl->color->value(frame).toColorCode();
	static mof::VertexXYZCUV vertices[4];
	vertices[0].x = -0.5f;
	vertices[0].y = 0.5f;
	vertices[0].z = 0;
	vertices[0].color = color;
	vertices[0].tu = textureCoordinates.beginX;
	vertices[0].tv = textureCoordinates.beginY;

	vertices[1].x = 0.5f;
	vertices[1].y = 0.5f;
	vertices[1].z = 0;
	vertices[1].color = color;
	vertices[1].tu = textureCoordinates.endX;
	vertices[1].tv = textureCoordinates.beginY;

	vertices[2].x = -0.5f;
	vertices[2].y = -0.5f;
	vertices[2].z = 0;
	vertices[2].color = color;
	vertices[2].tu = textureCoordinates.beginX;
	vertices[2].tv = textureCoordinates.endY;

	vertices[3].x = 0.5f;
	vertices[3].y = -0.5f;
	vertices[3].z = 0;
	vertices[3].color = color;
	vertices[3].tu = textureCoordinates.endX;
	vertices[3].tv = textureCoordinates.endY;

	mof::GraphicsDevice::setTexture(m_pImpl->pTexture.get());
	mof::Material mat;
	mat.ambientColor = mof::Color4f(color);
	mof::GraphicsDevice::setMaterial(mat);
	mof::Matrix3D::Array view = mof::GraphicsDevice::getViewTransform().getArray();// 一時コード（カメラの回転を無効）
	view.elements[3][0] = view.elements[3][1] = view.elements[3][2] = 0;
	mof::Matrix3D inv_view = mof::Matrix3D::createTransposed(mof::Matrix3D(view));
	mof::GraphicsDevice::setWorldTransform(inv_view * m_pImpl->worldMatrix->value(frame));
	//mof::GraphicsDevice::setWorldTransform(m_pImpl->worldMatrix->value(frame));
	mof::GraphicsDevice::drawVertexArray(vertices[0] , vertices[3] , PRIMITIVE_TYPE_TRIANGLESTRIP);
	
}

void mof::Board::setVisible(bool)
{
	// TODO
}

void mof::Board::setFrameNumber(mof::FrameNumber fn)
{
	m_pImpl->m_frame = fn;
}

