//-----------------------------------------------------------------------------------------------
// Renderer_OpenGL3_Win32.cpp
//
#include "GypsyPrecompiledHeader.hpp"
#include "Engine/Core/PlatformDefines.hpp"
#if defined( GYPSY_ENABLE_RENDERER )

//-----------------------------------------------------------------------------------------------
#include "Engine/Renderer/Renderer_OpenGL3_Win32.hpp"
#include "Engine/Renderer/OpenGLExtensions.hpp"
#include "Engine/Core/PlatformSpecificHeaders.hpp" // FIXME: necessary under Win32 as their GL.h depends on Windows.h - is there a cleaner way?
#include <gl/GL.h>
#include "ThirdParty/stb/stb_image.h"


/////////////////////////////////////////////////////////////////////////////////////////////////
// Texture_OpenGL3_Win32
//

//-----------------------------------------------------------------------------------------------
VIRTUAL void Texture_OpenGL3_Win32::PopulateFromFile( const char* imageFilePath, TextureFilterMode minFilter, TextureFilterMode magFilter, TextureEdgeMode edgeMode )
{
	int numChannels = 0; // Filled in for us to indicate how many color/alpha components the image had (e.g. 3=RGB, 4=RGBA)
	int numChannelsRequested = 0; // don't care; we [currently] only support 3 (RGB) or 4 (RGBA)
	IntVector2 dimensions( IntVector2::ZERO );
	unsigned char* imageData = stbi_load( imageFilePath, &dimensions.x, &dimensions.y, &numChannels, numChannelsRequested );
	if( !imageData )
		return;

	PopulateFromData( imageData, dimensions, numChannels, minFilter, magFilter, edgeMode );
	stbi_image_free( imageData );
}


/////////////////////////////////////////////////////////////////////////////////////////////////
// Renderer_OpenGL3_Win32
//

//-----------------------------------------------------------------------------------------------
Renderer_OpenGL3_Win32::Renderer_OpenGL3_Win32()
{
}


//-----------------------------------------------------------------------------------------------
Renderer_OpenGL3_Win32::~Renderer_OpenGL3_Win32()
{
}


//-----------------------------------------------------------------------------------------------
VIRTUAL void Renderer_OpenGL3_Win32::StartUp()
{
	CreateWin32OpenGLRenderingContext();
	DetermineCapabilityLevel(); // Have to do this a bit early ourselves since we want to remove advanced function bindings if we are simulating an older version, etc.
	BindAdvancedOpenGLFunctionPointers();
	Renderer_OpenGL3::StartUp();
}


//-----------------------------------------------------------------------------------------------
VIRTUAL void Renderer_OpenGL3_Win32::SwapBuffers()
{
	HWND hWnd = GetActiveWindow();
	HDC dc = GetDC( hWnd );
	::SwapBuffers( dc );
}


//-----------------------------------------------------------------------------------------------
VIRTUAL Texture* Renderer_OpenGL3_Win32::CreateTextureFromFile( const char* imageFilePath, TextureFilterMode minFilter, TextureFilterMode magFilter, TextureEdgeMode edgeMode )
{
	Texture_OpenGL3_Win32* newTexture = new Texture_OpenGL3_Win32();
	newTexture->PopulateFromFile( imageFilePath, minFilter, magFilter, edgeMode );
	if( newTexture->m_numChannels == 0 )
	{
		delete newTexture;
		newTexture = nullptr;
	}

	return newTexture;
}


//-----------------------------------------------------------------------------------------------
VIRTUAL void Renderer_OpenGL3_Win32::CreateWin32OpenGLRenderingContext()
{
	HWND windowHandle = GetActiveWindow();
	HDC deviceContext = GetDC( windowHandle );

	HCURSOR cursor = LoadCursor( NULL, IDC_ARROW );
	SetCursor( cursor );

	PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
	memset( &pixelFormatDescriptor, 0, sizeof( pixelFormatDescriptor ) );
	pixelFormatDescriptor.nSize			= sizeof( pixelFormatDescriptor );
	pixelFormatDescriptor.nVersion		= 1;
	pixelFormatDescriptor.dwFlags		= PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
	pixelFormatDescriptor.iPixelType	= PFD_TYPE_RGBA;
	pixelFormatDescriptor.cColorBits	= 24;
	pixelFormatDescriptor.cDepthBits	= 24;
	pixelFormatDescriptor.cAccumBits	= 0;
	pixelFormatDescriptor.cStencilBits	= 8;

	int pixelFormatCode = ChoosePixelFormat( deviceContext, &pixelFormatDescriptor );
	SetPixelFormat( deviceContext, pixelFormatCode, &pixelFormatDescriptor );
	HGLRC rc = wglCreateContext( deviceContext );
	wglMakeCurrent( deviceContext, rc );

	PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress( "wglSwapIntervalEXT" );
	if( wglSwapIntervalEXT )
		wglSwapIntervalEXT( 1 );

	// Set up OpenGL states the way we want 'em
	glMatrixMode( GL_MODELVIEW );
	glEnable( GL_BLEND );
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
	glEnable( GL_LINE_SMOOTH );
}


#endif // GYPSY_ENABLE_RENDERER
