#pragma once
#include "Box.h"
#include "Bindable.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "VertexShader.h"
#include "PixelShader.h"
#include "ConstantBuffer.h"
#include "InputLayout.h"
#include "Topology.h"
#include "TransformCBuf.h"
#include "Graphics.h"
#include <DirectXMath.h>
#include "Texture.h"
#include "Sampler.h"

Box::Box(Graphics& gfx, StructVertex vertices[], Logger& logger)
{
	// Assign values for vertex and texture
	/*for (int i = 0; i < 24; i++)
	{
		this->vertices[i] = vertices[i];
	}*/

	/************************************
	* 2.3 DefineVertexBuffer
	************************************/
	const std::vector<StructVertex> vb =
	{
		{ vertices[0] },
		{ vertices[1] },
		{ vertices[2] },
		{ vertices[3] },
		{ vertices[4] },
		{ vertices[5] },
		{ vertices[6] },
		{ vertices[7] },
		{ vertices[8] },
		{ vertices[9] },
		{ vertices[10] },
		{ vertices[11] },
		{ vertices[12] },
		{ vertices[13] },
		{ vertices[14] },
		{ vertices[15] },
		{ vertices[16] },
		{ vertices[17] },
		{ vertices[18] },
		{ vertices[19] },
		{ vertices[20] },
		{ vertices[21] },
		{ vertices[22] },
		{ vertices[23] },
	};

	AddBind(std::make_unique<VertexBuffer>(gfx, vb, logger));

	///************************************
	//* 2.6 DefineColorConstBuffer(PixelConstBuf)
	//************************************/
	//const StructPixelConstBuf cb2 =
	//{
	//	{
	//		{ color[0][0], color[0][1], color[0][2] },
	//		{ color[0][0], color[0][1], color[0][2] },
	//		{ color[1][0], color[1][1], color[1][2] },
	//		{ color[1][0], color[1][1], color[1][2] },
	//		{ color[2][0], color[2][1], color[2][2] },
	//		{ color[2][0], color[2][1], color[2][2] },
	//		{ color[3][0], color[3][1], color[3][2] },
	//		{ color[3][0], color[3][1], color[3][2] },
	//		{ color[4][0], color[4][1], color[4][2] },
	//		{ color[4][0], color[4][1], color[4][2] },
	//		{ color[5][0], color[5][1], color[5][2] },
	//		{ color[5][0], color[5][1], color[5][2] },
	//	}
	//};

	//AddBind(std::make_unique<PixelConstantBuffer<StructPixelConstBuf>>(gfx, cb2));

	/************************************
	* 2.5 DefineTransConstBuffer
	************************************/
	AddBind(std::make_unique<TransformCbuf>(gfx, *this));

	if (!IsStaticInitialized())
	{
		/************************************
		* 2.7 DefineVertexShader
		************************************/
		//auto pVertexShader = std::make_unique<VertexShader>(gfx, L"VertexShader.cso");
		auto pVertexShader = std::make_unique<VertexShader>(gfx, L"TextureVS.cso");
		auto pvsbc = pVertexShader->GetBytecode();
		//AddBind(std::move(pVertexShader));
		AddStaticBind(std::move(pVertexShader));

		/************************************
		* 2.8 DefinePixelShader
		************************************/
		//AddBind(std::make_unique<PixelShader>(gfx, L"PixelShader.cso"));
		//AddStaticBind(std::make_unique<PixelShader>(gfx, L"PixelShader.cso"));
		AddStaticBind(std::make_unique<PixelShader>(gfx, L"TexturePS.cso"));

		/************************************
		* 2.4 DefineIndexBuffer
		************************************/
		const std::vector<unsigned short> indices =
		{
			0,1,2, 2,1,3,
			4,5,6, 6,5,7,
			8,9,10, 10,9,11,
			12,13,14, 14,13,15,
			16,17,18, 18,17,19,
			20,21,22, 22,21,23,
		};

		//AddIndexBuffer(std::make_unique<IndexBuffer>(gfx, indices, logger));
		AddStaticIndexBuffer(std::make_unique<IndexBuffer>(gfx, indices, logger));

		/************************************
		* 2.9 DefineInputLayout
		************************************/
		const std::vector<D3D11_INPUT_ELEMENT_DESC> ied =
		{
			//{ "Position",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 },
			{ "Position",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0 },
		    { "TexCoord",0,DXGI_FORMAT_R32G32_FLOAT,0,12,D3D11_INPUT_PER_VERTEX_DATA,0 },
			{ "ImageSlot",0,DXGI_FORMAT_R32_FLOAT ,0,20,D3D11_INPUT_PER_VERTEX_DATA,0 },
		};
		//AddBind(std::make_unique<InputLayout>(gfx, ied, pvsbc));
		AddStaticBind(std::make_unique<InputLayout>(gfx, ied, pvsbc));

		/************************************
		* 2.10 DefinePrimitiveTopology
		************************************/
		//AddBind(std::make_unique<Topology>(gfx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST));
		AddStaticBind(std::make_unique<Topology>(gfx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST));

		///************************************
		//* 2.21 DefineTextureForEachSurface
		//************************************/
		//for (int i = 0; i < 6; i++) {
		//	AddStaticBind(std::make_unique<Texture>(gfx, surface[i]));
		//}

		/************************************
		* 2.22 DefineSampler
		************************************/
		AddStaticBind(std::make_unique<Sampler>(gfx));
	}
	else
	{
		SetIndexFromStatic();
	}
}

void Box::Update(float dt) noexcept
{
	/*roll += droll * dt;
	pitch += dpitch * dt;
	yaw += dyaw * dt;
	theta += dtheta * dt;
	phi += dphi * dt;
	chi += dchi * dt;*/
	//dx = dt;
	//dy = dt;
	//dz = dt * 10.0f;
}

//void Box::UpdateCamera(float sin, float cos) noexcept
//{
//	using namespace DirectX;
//	upDirection = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f);
//	focusPosition = XMVectorZero();
//	eyePosition = XMVectorSet(20.0f * sin, 10.0f, -20.0f * cos, 1.0f);
//};

DirectX::XMMATRIX Box::GetTransformXM(Graphics& gfx) const noexcept
{
	/*return DirectX::XMMatrixRotationRollPitchYaw(pitch, yaw, roll) *
		DirectX::XMMatrixTranslation(r, 0.0f, 0.0f) *
		DirectX::XMMatrixRotationRollPitchYaw(theta, phi, chi) *
		DirectX::XMMatrixTranslation(0.0f, 0.0f, 20.0f);*/

	DirectX::XMMATRIX lookAtMatrix = gfx.getLookAtMatrix();

	return
		DirectX::XMMatrixTranslation(dx, dy, dz)
		//* DirectX::XMMatrixLookAtLH(eyePosition, focusPosition, upDirection);
		* lookAtMatrix;
}