#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9core.h>

#define null NULL

struct Objeto
{
	IDirect3DTexture9* Textura;
	D3DXVECTOR3 Posicion;
};

struct ObjetoBola : public Objeto
{
	int VelX, VelY;
};

IDirect3D9* D3D9 = null;
IDirect3DDevice9* D3D9Dispositivo = null;
ID3DXSprite* Sprite;

Objeto* PaletaJugador;
Objeto* PaletaCPU;
ObjetoBola* Bola;

void Liberar();

long Iniciar(HWND hWindow)
{
	if (null == (D3D9 = Direct3DCreate9(D3D_SDK_VERSION)))
		return E_FAIL;
	D3DDISPLAYMODE ModosDisplay = {0};
	D3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &ModosDisplay);

	D3DPRESENT_PARAMETERS pPresentacion = {0};
	pPresentacion.Windowed = true;
	pPresentacion.SwapEffect = D3DSWAPEFFECT_DISCARD;
	pPresentacion.BackBufferFormat = ModosDisplay.Format;
	pPresentacion.EnableAutoDepthStencil = true;
	pPresentacion.AutoDepthStencilFormat = D3DFMT_D16;

	if (FAILED(D3D9->CreateDevice(D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		hWindow,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&pPresentacion,
		&D3D9Dispositivo)))
	{
		return E_FAIL;
	}

	::D3D9Dispositivo->SetRenderState(D3DRS_ALPHABLENDENABLE, true);

	if (FAILED(D3DXCreateSprite(::D3D9Dispositivo, &Sprite)))
		return E_FAIL;

	::PaletaJugador = new Objeto();
	::PaletaJugador->Posicion = D3DXVECTOR3(5.0f, 200.0f, 0.0f);
	if (FAILED(D3DXCreateTextureFromFile(::D3D9Dispositivo, L"tJugador.jpg", &PaletaJugador->Textura)))
		return E_FAIL;

	::PaletaCPU = new Objeto();
	::PaletaCPU->Posicion = D3DXVECTOR3(758.0f, 200.0f, 0.0f);
	if (FAILED(D3DXCreateTextureFromFile(::D3D9Dispositivo, L"tCPU.jpg", &PaletaCPU->Textura)))
		return E_FAIL;
	
	::Bola = new ObjetoBola();
	::Bola->Posicion = D3DXVECTOR3(350.0f, 250.0f, 0.0f);
	::Bola->VelX = ::Bola->VelY = 2;
	if (FAILED(D3DXCreateTextureFromFile(::D3D9Dispositivo, L"tBola.jpg", &Bola->Textura)))
		return E_FAIL;

	::D3D9Dispositivo->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

	return S_OK;
}

void Update()
{
	::Bola->Posicion.x += ::Bola->VelX;
	::Bola->Posicion.y += ::Bola->VelY;
	
	//IA
	if (::PaletaCPU->Posicion.y + 64 < Bola->Posicion. y)
		PaletaCPU->Posicion.y += 3.0f;
	else if (::PaletaCPU->Posicion.y + 64 > Bola->Posicion. y)
		PaletaCPU->Posicion.y -= 3.0f;

	//Colisiones 
	if (::Bola->Posicion.y <= 0.0f)
		::Bola->VelY *= -1;
	else if (::Bola->Posicion.y + 32.0f + 24.0f >= 600.0f)
		Bola->VelY *= -1;

	if (Bola->Posicion.x <= 0.0f)
		Bola->VelX *= -1;
	else if (Bola->Posicion.x + 32.0f >= 800.0f)
		Bola->VelX *= -1;

	if (::PaletaJugador->Posicion.y <= 0.0f)
		::PaletaJugador->Posicion.y = 0.0f;
	if (::PaletaJugador->Posicion.y + 160.0f >= 600.0f)
		::PaletaJugador->Posicion.y = 440.0f;
	
	if (::PaletaCPU->Posicion.y <= 0.0f)
		::PaletaCPU->Posicion.y = 0.0f;
	if (::PaletaCPU->Posicion.y + 160.0f >= 600.0f)
		::PaletaCPU->Posicion.y = 440.0f;
	
	if (Bola->Posicion.x < ::PaletaJugador->Posicion.x + 32)
	{
		if (Bola->Posicion.y + 16.0f < ::PaletaJugador->Posicion.y ||
			Bola->Posicion.y + 16.0f > ::PaletaJugador->Posicion.y + 128.0f)
		{
			MessageBox(null, L"Has perdido", L"Has perdido", MB_OK);
			::Liberar();
			exit(0); // GAME OVER
		}
		else
			Bola->VelX *= -1;
	}
	if (Bola->Posicion.x + 33.0f > ::PaletaCPU->Posicion.x)
				Bola->VelX *= -1;

	
}

void Renderear()
{
	if (::D3D9Dispositivo == null)
		return;
	::D3D9Dispositivo->Clear(0, null, D3DCLEAR_TARGET, 0xFFFFFFFF, 1.0f, 0);
	if (SUCCEEDED(::D3D9Dispositivo->BeginScene()))
	{
		if (SUCCEEDED(::Sprite->Begin(D3DXSPRITE_ALPHABLEND)))
		{
			::Sprite->Draw(::PaletaJugador->Textura, null, null, &::PaletaJugador->Posicion, 0xFFFFFFFF);
			::Sprite->Draw(::PaletaCPU->Textura, null, null, &::PaletaCPU->Posicion, 0xFFFFFFFF);
			::Sprite->Draw(::Bola->Textura, null, null, &::Bola->Posicion, 0xFFFFFFFF);
			::Sprite->End();
		}
		::D3D9Dispositivo->EndScene();
	}
	::D3D9Dispositivo->Present(null, null, null, null);
}

void Liberar()
{
	if (::Sprite != null)
		::Sprite->Release();

	if (::PaletaCPU->Textura != null)
		::PaletaCPU->Textura->Release();

	if (::PaletaJugador->Textura != null)
		::PaletaJugador->Textura->Release();

	if (::Bola->Textura != null)
		::Bola->Textura->Release();

	if(::D3D9Dispositivo != null) 
        ::D3D9Dispositivo->Release();

    if(::D3D9 != null)
        ::D3D9->Release();

}

__w64 long __stdcall Procedimientos(HWND hWindow,
									unsigned int Mensaje,
									__w64 unsigned int wParametros,
									__w64 long lParametros)
{
	switch(Mensaje)
    {
	case WM_KEYDOWN:
		{
			switch(wParametros)
			{
			case VK_UP:
				::PaletaJugador->Posicion.y -= 4.0f; break;
			case VK_DOWN:
				::PaletaJugador->Posicion.y += 4.0f; break;
			case VK_ESCAPE:
				{
					Liberar();
					PostQuitMessage(0);
					return 0;
				}
			}
			break;
		}
	case WM_DESTROY:
		{
			Liberar();
			PostQuitMessage(0);
			return 0;
		}
	}
	return DefWindowProc( hWindow, Mensaje, wParametros, lParametros );
}

int __stdcall WinMain(HINSTANCE hInst, HINSTANCE, char*, int)
{
	WNDCLASSEX ClaseWnd = {0};
	ClaseWnd.cbSize = sizeof(ClaseWnd);	
	ClaseWnd.lpszClassName = L"PrimerF5";
	ClaseWnd.lpfnWndProc = Procedimientos;
	ClaseWnd.style = CS_CLASSDC;
	ClaseWnd.hInstance = GetModuleHandle(null);
	RegisterClassEx(&ClaseWnd);
	HWND hWindow = CreateWindow(L"PrimerF5",
		L"PrimerF5",
		WS_SYSMENU,
		10, 
		10, 
		800, 
		600, 
		null, 
		null, 
		ClaseWnd.hInstance,
		null);

	if (SUCCEEDED(::Iniciar(hWindow)))
	{
		ShowWindow(hWindow, SW_SHOWDEFAULT);
		UpdateWindow(hWindow);
		MSG Mensaje;
		ZeroMemory(&Mensaje, sizeof(Mensaje));
		while (Mensaje.message != WM_QUIT)
		{
			if (PeekMessage(&Mensaje, null, 0U, 0U, PM_REMOVE))
			{
				TranslateMessage(&Mensaje);
				DispatchMessage(&Mensaje);
			}
			else
			{
				::Update();
				::Renderear();				
			}
		}
	}
	UnregisterClass(L"PrimerF5", ClaseWnd.hInstance );
	return 0;
}