#include "sysinc.h"
#include "mgl/gl.h"
#include <math.h>
#include "minigl.library_rev.h"

#include <exec/exec.h>


#include "minigl_vectors.c"


extern void MGLTerm(void);
extern GLboolean MGLInit(void);
APTR segList = 0;

struct Library *
libOpen(struct LibraryManagerInterface *Self, ULONG version)
{
	struct Library *libBase = Self->Data.LibBase;

	dprintf("In libOpen\n");

	/* Add up the open count */
	libBase->lib_OpenCnt++;

	/* Clear pending expunge */
	libBase->lib_Flags &= ~LIBF_DELEXP;

	return libBase;
}

APTR 
libExpunge(struct LibraryManagerInterface *Self)
{
	struct Library *libBase = Self->Data.LibBase;

	/* Check if we're still open */
	if (libBase->lib_OpenCnt)
	{
		/* We are, delay the expunge */
		libBase->lib_Flags |= LIBF_DELEXP;
		return 0;
	}

	MGLTerm();
	
	/* No one uses us, so really expunge. Start by removing us from the library list */
	IExec->Remove((struct Node *)libBase);

	/* Delete ourselves */
	IExec->DeleteLibrary(libBase);
	IExec->Release();

	/* Finally, return the handle so whoever loaded us into memory can get rid of us */
	return segList;
}

APTR 
libClose(struct LibraryManagerInterface *Self)
{
	struct Library *libBase = Self->Data.LibBase;

	/* Make the close count */
	libBase->lib_OpenCnt--;

	/* If we're still open, do nothing */
	if (libBase->lib_OpenCnt > 0)
		return 0;

	/* Otherwise, if an expunge is pending, execute it now */
	if (libBase->lib_Flags & LIBF_DELEXP)
	{
		return libExpunge(Self);
	}

	return 0;
}

struct Library *
libInit(struct Library *libBase, APTR seglist, struct Interface *exec)
{
	/* Initialize the library base */
	dprintf("Initializing library base %p, IExec = %p\n", libBase, exec);
	libBase->lib_Node.ln_Type = NT_LIBRARY;
	libBase->lib_Node.ln_Pri  = 0;
	libBase->lib_Node.ln_Name = (char *)"minigl.library";
	libBase->lib_Flags        = LIBF_SUMUSED|LIBF_CHANGED;
	libBase->lib_Version      = (int)VERSION;
	libBase->lib_Revision     = (int)REVISION;
	libBase->lib_IdString     = (char *)VSTRING;

	segList = seglist;
	IExec = (struct ExecIFace *)exec;

	SysBase = IExec->Data.LibBase;
	
	DOSBase = IExec->OpenLibrary("dos.library", 0);
	IDOS = (struct DOSIFace *)IExec->GetInterface(DOSBase, "main", 1, NULL);

	if (MGLInit() == GL_FALSE)
	{
		dprintf("Error during MGLInit()\n");
		IExec->DropInterface((struct Interface *)IDOS);
		IExec->CloseLibrary(DOSBase);
		return 0;
	}
	
	dprintf("Done\n");

	/* Return libBase here to indicate success, or 0 if something failed */
	return libBase;
}

uint32 defaultObtain(struct Interface *Self)
{
	return ++Self->Data.RefCount;
}

uint32 defaultRelease(struct Interface *Self)
{
	return --Self->Data.RefCount;
}

uint32 mgl_Obtain(struct MiniGLIFace *Self)
{
	return ++Self->Data.RefCount;
}

uint32 mgl_Release(struct MiniGLIFace *Self)
{
	return --Self->Data.RefCount;
}

uint32 cgl_Obtain(struct GLContextIFace *Self)
{
	return ++Self->Data.RefCount;
}

uint32 cgl_Release(struct GLContextIFace *Self)
{
	return --Self->Data.RefCount;
}
/* Manager interface vectors */
void *manager_vectors[] =
{
	(void *)defaultObtain,
	(void *)defaultRelease,
	(void *)0,
	(void *)0,
	(void *)libOpen,
	(void *)libClose,
	(void *)libExpunge,
	(void *)0,
	(void *)-1,
};

/* "__library" interface tag list */
struct TagItem managerTags[] =
{
	{MIT_Name,             (ULONG)"__library"},
	{MIT_VectorTable,      (ULONG)manager_vectors},
	{MIT_Version,          1},
	{TAG_DONE,             0}
};

struct TagItem mainTags[] =
{
	{MIT_Name,             (ULONG)"main"},
	{MIT_VectorTable,      (ULONG)main_vectors},
	{MIT_Version,          1},
	{TAG_DONE,             0}
};

uint32 libInterfaces[] =
{
	(uint32)managerTags,
	(uint32)mainTags,
	0
};

struct TagItem libCreateTags[] =
{
	{CLT_DataSize,		(uint32)sizeof(struct Library)},
	{CLT_InitFunc,		(uint32)libInit},
	{CLT_Interfaces,	(uint32)libInterfaces},
	{TAG_DONE,			0},
};
	
struct Resident minigl_res __attribute__((used)) =
{
	RTC_MATCHWORD,
	&minigl_res,
	&minigl_res+1,
	RTF_AUTOINIT|RTF_NATIVE|RTF_COLDSTART,
	(int)VERSION,
	NT_LIBRARY,
	0,
	(char *)"minigl.library",
	(char *)VSTRING,
	libCreateTags
};

void _start(void)
{
}

