/*
 * Copyright 2006-2012, Haiku. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Jérôme Duval, korli@users.berlios.de
 *		Philippe Houdoin, philippe.houdoin@free.fr
 *		Stefano Ceccherini, burton666@libero.it
 */

#include <kernel/image.h>

#include <GLView.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <DirectWindow.h>
#include <GLRenderer.h>

#include "interface/DirectWindowPrivate.h"
#include "GLDispatcher.h"
#include "GLRendererRoster.h"


struct glview_direct_info {
	direct_buffer_info* direct_info;
	bool direct_connected;
	bool enable_direct_mode;

	glview_direct_info();
	~glview_direct_info();
};


BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode,
	ulong options)
	:
	BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
		//  | B_FULL_UPDATE_ON_RESIZE)
	fGc(NULL),
	fOptions(options),
	fDitherCount(0),
	fDrawLock("BGLView draw lock"),
	fDisplayLock("BGLView display lock"),
	fClipInfo(NULL),
	fRenderer(NULL),
	fRoster(NULL),
	fDitherMap(NULL)
{
	fRoster = new GLRendererRoster(this, options);
}


BGLView::~BGLView()
{
	delete fClipInfo;
	if (fRenderer)
		fRenderer->Release();
}


void
BGLView::LockGL()
{
	// TODO: acquire the OpenGL API lock it on this glview

	fDisplayLock.Lock();
	if (fRenderer)
		fRenderer->LockGL();
}


void
BGLView::UnlockGL()
{
	if (fRenderer)
		fRenderer->UnlockGL();
	fDisplayLock.Unlock();

	// TODO: release the GL API lock to others glviews
}


void
BGLView::SwapBuffers()
{
	SwapBuffers(false);
}


void
BGLView::SwapBuffers(bool vSync)
{
	if (fRenderer) {
		_LockDraw();
		fRenderer->SwapBuffers(vSync);
		_UnlockDraw();
	}
}


BView*
BGLView::EmbeddedView()
{
	return NULL;
}


void*
BGLView::GetGLProcAddress(const char* procName)
{
	BGLDispatcher* glDispatcher = NULL;

	if (fRenderer)
		glDispatcher = fRenderer->GLDispatcher();

	if (glDispatcher)
		return (void*)glDispatcher->AddressOf(procName);

	return NULL;
}


status_t
BGLView::CopyPixelsOut(BPoint source, BBitmap* dest)
{
	if (!fRenderer)
		return B_ERROR;

	if (!dest || !dest->Bounds().IsValid())
		return B_BAD_VALUE;

	return fRenderer->CopyPixelsOut(source, dest);
}


status_t
BGLView::CopyPixelsIn(BBitmap* source, BPoint dest)
{
	if (!fRenderer)
		return B_ERROR;

	if (!source || !source->Bounds().IsValid())
		return B_BAD_VALUE;

	return fRenderer->CopyPixelsIn(source, dest);
}


/*!	Mesa's GLenum is not ulong but uint, so we can't use GLenum
	without breaking this method signature.
	Instead, we have to use the effective BeOS's SGI OpenGL GLenum type:
	unsigned long.
 */
void
BGLView::ErrorCallback(unsigned long errorCode)
{
	char msg[32];
	sprintf(msg, "GL: Error code $%04lx.", errorCode);
	// TODO: under BeOS R5, it call debugger(msg);
	fprintf(stderr, "%s\n", msg);
}


void
BGLView::Draw(BRect updateRect)
{
	if (fRenderer) {
		_LockDraw();
		fRenderer->Draw(updateRect);
		_UnlockDraw();
		return;
	}
	// TODO: auto-size and center the string
	MovePenTo(8, 32);
	DrawString("No OpenGL renderer available!");
}


void
BGLView::AttachedToWindow()
{
	BView::AttachedToWindow();

	fBounds = Bounds();
	for (BView* view = this; view != NULL; view = view->Parent())
		view->ConvertToParent(&fBounds);

	fRenderer = fRoster->GetRenderer();
	if (fRenderer != NULL) {
		// Jackburton: The following code was commented because it doesn't look
		// good in "direct" mode:
		// when the window is moved, the app_server doesn't paint the view's
		// background, and the stuff behind the window itself shows up.
		// Setting the view color to black, instead, looks a bit more elegant.
#if 0
		// Don't paint white window background when resized
		SetViewColor(B_TRANSPARENT_32_BIT);
#else
		SetViewColor(0, 0, 0);
#endif

		// Set default OpenGL viewport:
		LockGL();
		glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight());
		UnlockGL();
		fRenderer->FrameResized(Bounds().IntegerWidth(),
			Bounds().IntegerHeight());

		if (fClipInfo) {
			fRenderer->DirectConnected(fClipInfo->direct_info);
			fRenderer->EnableDirectMode(fClipInfo->enable_direct_mode);
		}

		return;
	}

	fprintf(stderr, "no renderer found! \n");

	// No Renderer, no rendering. Setup a minimal "No Renderer" string drawing
	// context
	SetFont(be_bold_font);
	// SetFontSize(16);
}


void
BGLView::AllAttached()
{
	BView::AllAttached();
}


void
BGLView::DetachedFromWindow()
{
	if (fRenderer)
		fRenderer->Release();
	fRenderer = NULL;

	BView::DetachedFromWindow();
}


void
BGLView::AllDetached()
{
	BView::AllDetached();
}


void
BGLView::FrameResized(float width, float height)
{
	fBounds = Bounds();
	for (BView* v = this; v; v = v->Parent())
		v->ConvertToParent(&fBounds);

	if (fRenderer) {
		LockGL();
		_LockDraw();
		_CallDirectConnected();
		fRenderer->FrameResized(width, height);
		_UnlockDraw();
		UnlockGL();
	}

	BView::FrameResized(width, height);
}


status_t
BGLView::Perform(perform_code d, void* arg)
{
	return BView::Perform(d, arg);
}


status_t
BGLView::Archive(BMessage* data, bool deep) const
{
	return BView::Archive(data, deep);
}


void
BGLView::MessageReceived(BMessage* msg)
{
	BView::MessageReceived(msg);
}


void
BGLView::SetResizingMode(uint32 mode)
{
	BView::SetResizingMode(mode);
}


void
BGLView::GetPreferredSize(float* _width, float* _height)
{
	if (_width)
		*_width = 0;
	if (_height)
		*_height = 0;
}


void
BGLView::Show()
{
	BView::Show();
}


void
BGLView::Hide()
{
	BView::Hide();
}


BHandler*
BGLView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
	int32 form, const char* property)
{
	return BView::ResolveSpecifier(msg, index, specifier, form, property);
}


status_t
BGLView::GetSupportedSuites(BMessage* data)
{
	return BView::GetSupportedSuites(data);
}


void
BGLView::DirectConnected(direct_buffer_info* info)
{
	if (fClipInfo == NULL) {
		fClipInfo = new (std::nothrow) glview_direct_info();
		if (fClipInfo == NULL)
			return;
	}

	direct_buffer_info* localInfo = fClipInfo->direct_info;

	switch (info->buffer_state & B_DIRECT_MODE_MASK) {
		case B_DIRECT_START:
			fClipInfo->direct_connected = true;
			memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
			_UnlockDraw();
			break;

		case B_DIRECT_MODIFY:
			_LockDraw();
			memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
			_UnlockDraw();
			break;

		case B_DIRECT_STOP:
			fClipInfo->direct_connected = false;
			_LockDraw();
			break;
	}

	if (fRenderer)
		_CallDirectConnected();
}


void
BGLView::EnableDirectMode(bool enabled)
{
	if (fRenderer)
		fRenderer->EnableDirectMode(enabled);
	if (fClipInfo == NULL) {
		fClipInfo = new (std::nothrow) glview_direct_info();
		if (fClipInfo == NULL)
			return;
	}

	fClipInfo->enable_direct_mode = enabled;
}


void
BGLView::_LockDraw()
{
	if (!fClipInfo || !fClipInfo->enable_direct_mode)
		return;

	fDrawLock.Lock();
}


void
BGLView::_UnlockDraw()
{
	if (!fClipInfo || !fClipInfo->enable_direct_mode)
		return;

	fDrawLock.Unlock();
}


void
BGLView::_CallDirectConnected()
{
	if (!fClipInfo)
		return;

	direct_buffer_info* localInfo = fClipInfo->direct_info;
	direct_buffer_info* info = (direct_buffer_info*)malloc(
		DIRECT_BUFFER_INFO_AREA_SIZE);
	if (info == NULL)
		return;

	memcpy(info, localInfo, DIRECT_BUFFER_INFO_AREA_SIZE);

	// Collect the rects into a BRegion, then clip to the view's bounds
	BRegion region;
	for (uint32 c = 0; c < localInfo->clip_list_count; c++)
		region.Include(localInfo->clip_list[c]);
	BRegion boundsRegion = fBounds.OffsetByCopy(localInfo->window_bounds.left,
		localInfo->window_bounds.top);
	info->window_bounds = boundsRegion.RectAtInt(0);
		// window_bounds are now view bounds
	region.IntersectWith(&boundsRegion);

	info->clip_list_count = region.CountRects();
	info->clip_bounds = region.FrameInt();

	for (uint32 c = 0; c < info->clip_list_count; c++)
		info->clip_list[c] = region.RectAtInt(c);
	fRenderer->DirectConnected(info);
	free(info);
}


//---- virtual reserved methods ----------


void BGLView::_ReservedGLView1() {}
void BGLView::_ReservedGLView2() {}
void BGLView::_ReservedGLView3() {}
void BGLView::_ReservedGLView4() {}
void BGLView::_ReservedGLView5() {}
void BGLView::_ReservedGLView6() {}
void BGLView::_ReservedGLView7() {}
void BGLView::_ReservedGLView8() {}


// #pragma mark -


// BeOS compatibility: contrary to others BView's contructors,
// BGLView one wants a non-const name argument.
BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode,
	ulong options)
	:
	BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
	fGc(NULL),
	fOptions(options),
	fDitherCount(0),
	fDrawLock("BGLView draw lock"),
	fDisplayLock("BGLView display lock"),
	fClipInfo(NULL),
	fRenderer(NULL),
	fRoster(NULL),
	fDitherMap(NULL)
{
	fRoster = new GLRendererRoster(this, options);
}


#if 0
// TODO: implement BGLScreen class...


BGLScreen::BGLScreen(char* name, ulong screenMode, ulong options,
		status_t* error, bool debug)
	:
	BWindowScreen(name, screenMode, error, debug)
{
}


BGLScreen::~BGLScreen()
{
}


void
BGLScreen::LockGL()
{
}


void
BGLScreen::UnlockGL()
{
}


void
BGLScreen::SwapBuffers()
{
}


void
BGLScreen::ErrorCallback(unsigned long errorCode)
{
	// Mesa's GLenum is not ulong but uint!
	char msg[32];
	sprintf(msg, "GL: Error code $%04lx.", errorCode);
	// debugger(msg);
	fprintf(stderr, "%s\n", msg);
	return;
}


void
BGLScreen::ScreenConnected(bool enabled)
{
}


void
BGLScreen::FrameResized(float width, float height)
{
	return BWindowScreen::FrameResized(width, height);
}


status_t
BGLScreen::Perform(perform_code d, void* arg)
{
	return BWindowScreen::Perform(d, arg);
}


status_t
BGLScreen::Archive(BMessage* data, bool deep) const
{
	return BWindowScreen::Archive(data, deep);
}


void
BGLScreen::MessageReceived(BMessage* msg)
{
	BWindowScreen::MessageReceived(msg);
}


void
BGLScreen::Show()
{
	BWindowScreen::Show();
}


void
BGLScreen::Hide()
{
	BWindowScreen::Hide();
}


BHandler*
BGLScreen::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier,
	int32 form, const char* property)
{
	return BWindowScreen::ResolveSpecifier(msg, index, specifier,
		form, property);
}


status_t
BGLScreen::GetSupportedSuites(BMessage* data)
{
	return BWindowScreen::GetSupportedSuites(data);
}


//---- virtual reserved methods ----------

void BGLScreen::_ReservedGLScreen1() {}
void BGLScreen::_ReservedGLScreen2() {}
void BGLScreen::_ReservedGLScreen3() {}
void BGLScreen::_ReservedGLScreen4() {}
void BGLScreen::_ReservedGLScreen5() {}
void BGLScreen::_ReservedGLScreen6() {}
void BGLScreen::_ReservedGLScreen7() {}
void BGLScreen::_ReservedGLScreen8() {}
#endif


const char* color_space_name(color_space space)
{
#define C2N(a)	case a:	return #a

	switch (space) {
	C2N(B_RGB24);
	C2N(B_RGB32);
	C2N(B_RGBA32);
	C2N(B_RGB32_BIG);
	C2N(B_RGBA32_BIG);
	C2N(B_GRAY8);
	C2N(B_GRAY1);
	C2N(B_RGB16);
	C2N(B_RGB15);
	C2N(B_RGBA15);
	C2N(B_CMAP8);
	default:
		return "Unknown!";
	};

#undef C2N
};


glview_direct_info::glview_direct_info()
{
	// TODO: See direct_window_data() in app_server's ServerWindow.cpp
	direct_info = (direct_buffer_info*)calloc(1, DIRECT_BUFFER_INFO_AREA_SIZE);
	direct_connected = false;
	enable_direct_mode = false;
}


glview_direct_info::~glview_direct_info()
{
	free(direct_info);
}

