////////////////////////////////////////////////////////
//
// GEM - Graphics Environment for Multimedia
//
// mdanks@cybermed.ucsd.edu
//
// Implementation file
//
//    Copyright (c) 1997-1998 Mark Danks.
//    For information on usage and redistribution, and for a DISCLAIMER OF ALL
//    WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution.
//
/////////////////////////////////////////////////////////

#include "GemWinCreate.h"

#include "m_pd.h"

static int s_buffer = 2;

BOOL bSetupPixelFormat(HDC hdc)
{
    PIXELFORMATDESCRIPTOR pfd;
	
	// clean out the descriptor
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
    
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    if (s_buffer == 1)
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
    else
        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.dwLayerMask = PFD_MAIN_PLANE;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
	pfd.cRedBits = 8;
	pfd.cBlueBits = 8;
	pfd.cGreenBits = 8;
    pfd.cDepthBits = 16;
    pfd.cAccumBits = 0;
    pfd.cStencilBits = 0;

    int pixelformat;
    if ( (pixelformat = ChoosePixelFormat(hdc, &pfd)) == 0 )
    {
        post("GEM: ChoosePixelFormat failed");
        return(FALSE);
    }
    if (SetPixelFormat(hdc, pixelformat, &pfd) == FALSE)
    {
        post("GEM: SetPixelFormat failed");
        return(FALSE);
    }
    return(TRUE);
}

LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	// assume that we handle the message
    long lRet = 0;
    switch (uMsg)
    {
		// we want to override these messages
   	    case WM_DESTROY:
       	case WM_CLOSE:
	    case WM_CREATE:
		    break;

        case WM_SIZE:
			// eventually, we should respond to this message and 
			//		change the OpenGL viewport...
            break;

        // pass all unhandled messages to DefWindowProc
        default:
            lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
            break;
    }
    return(lRet);
}

int createGemWindow(WindowInfo &info, WindowHints &hints)
{
    static int firstTime = 1;
    
	// store the buffer request in the static holding variable
    s_buffer = hints.buffer;

    // Register the frame class
    HINSTANCE hInstance = GetModuleHandle(NULL);
    if (!hInstance)
    {
        post("GEM: Unable to get module instance");
        return(0);
    }
    if (firstTime)
    {
        WNDCLASS wndclass;
        wndclass.style         = 0;
        wndclass.lpfnWndProc   = (WNDPROC)MainWndProc;
        wndclass.cbClsExtra    = 0;
        wndclass.cbWndExtra    = 0;
        wndclass.hInstance     = hInstance;
        wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wndclass.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
        wndclass.hbrBackground = NULL;
        wndclass.lpszMenuName  = NULL;
        wndclass.lpszClassName = "GEM";

        if (!RegisterClass(&wndclass) )
        {
            post("GEM: Unable to register window class");
            return(0);
        }
        firstTime = 0;
    }
    // Create the window
    info.win = CreateWindow ("GEM",
             "GEM",
	         WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
             0,
             0,
             hints.width,
             hints.height,
             NULL,
             NULL,
             hInstance,
             NULL);
    if (!info.win)
    {
        post("GEM: Unable to create window");
        return(0);
    }

	// create the device context
    info.dc = GetDC(info.win);
	if (!info.dc)
	{
		post("GEM: Unable to create device context");
		destroyGemWindow(info);
		return(0);
	}

	// set the pixel format for the window
    if (!bSetupPixelFormat(info.dc))
    {
        post("GEM: Unable to set window pixel format");
		destroyGemWindow(info);
        return(0);
    }

	// create the OpenGL context
    info.context = wglCreateContext(info.dc);
	if (!info.context)
	{
		post("GEM: Unable to create OpenGL context");
		destroyGemWindow(info);
		return(0);
	}

	// do we share display lists?
    if (hints.shared) wglShareLists(hints.shared, info.context);

	// make the context the current rendering context
    if (!wglMakeCurrent(info.dc, info.context))
	{
		post("GEM: Unable to make OpenGL context current");
		destroyGemWindow(info);
		return(0);
	}

    if (!hints.actuallyDisplay) return(1);

    // show and update main window
    ShowWindow(info.win, SW_SHOWNORMAL);

    UpdateWindow(info.win);
    
    return(1);
}

void destroyGemWindow(WindowInfo &info)
{
	if (info.win)
	{
		if (info.dc)
		{
			if (info.context)
			{
			    wglDeleteContext(info.context);
			}
		    ReleaseDC(info.win, info.dc);
		}
	    DestroyWindow(info.win);
	}
    info.dc  = NULL;
	info.win = NULL;
	info.dc  = NULL;
}
