/*-------------------------------------------------------------------------------
  Main.c (GLArea_Demo)
  Version 1.4
  Date: 26.12.2000
  Author: Bodmer Stephan [sbodmer@lsi-media.ch]
  Note: MUI Demo application for testing GLArea.mcc/ImageDB.mcc  objects
	GCC (EGCS) port *ONLY*
---------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <exec/exec.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <intuition/intuition.h>
#include <utility/tagitem.h>
#include <libraries/mui.h>

#include <proto/graphics.h>
#include <proto/asl.h>
#include <proto/dos.h>
#include <proto/alib.h>
#include <proto/dos.h>
#include <proto/muimaster.h>

#include <mui/GLArea_mcc.h>
#include <mui/ImageDB_mcc.h>

#include "Main.h"
#include "GLFunctions.h"

#include "MUI_GLArea_Demo.h"


extern struct ExecBase *SysBase;
struct Library *MUIMasterBase=NULL;

//--- GNU C specific
int __openliberror;
const unsigned long __stack=300000;

//--- Custom Shared variables (between GLArea objects used in the drawfuntions)
struct GLImage *groundimage=NULL,*backimage=NULL,*objimage=NULL;
struct GLTex *groundtex=NULL,*backtex=NULL,*objtex=NULL;

//--- MUI objects
struct ObjApp *MyApp=NULL;

//--- Globals
int object=CUBE;
int rendering=SOLID;
// ULONG displayid=0;
// int displaydepth=16;
// struct Screen *RenderScreen=NULL;
ULONG glarea_version=0,glarea_revision=0,imdb_version=0,imdb_revision=0;

char dir[255],name[255],filename[255];

/*
//--- Full screen option NOT YET USED
//----------------- Return the display mode name -------------------------
void ConvertDisplayID (char *st,int id) {
   struct NameInfo ni;
   if (GetDisplayInfoData(NULL,
			  (UBYTE *) &ni,
			  sizeof(struct NameInfo),
			  DTAG_NAME,
			  (ULONG) id)) {
      strncpy(st,(char *) ni.Name,255);
   };
}


ULONG StartScreen(Object *me __asm("a0"), Object *obj __asm("a2"), struct TagItem *tags __asm("a1")) {
    // puts("StartScreen");
    tags[0].ti_Tag=ASLSM_DoDepth;tags[0].ti_Data=TRUE;
    tags[1].ti_Tag=ASLSM_InitialDisplayID;tags[1].ti_Data=displayid;
    tags[2].ti_Tag=ASLSM_InitialDisplayDepth;tags[2].ti_Data=displaydepth;
    tags[3].ti_Tag=TAG_DONE;tags[3].ti_Data=0L;

    return TRUE;
}

ULONG StopScreen(Object *me __asm("a0"), Object *obj __asm("a2"), struct ScreenModeRequester *req __asm("a1")) {
    char idname[255];

    // puts("StopScreen");
    if (req==NULL) {
	// puts("Req is NULL");
	return 0;
    };
    displayid=(int) req->sm_DisplayID;
    displaydepth=(int) req->sm_DisplayDepth;
    // printf("DisplayID:%x\n",settings.displayID);
    ConvertDisplayID(idname,displayid);
    // printf("Name:%s\n",idname);
    SetAttrs((Object *) MyApp->STR_PA_ScreenMode, MUIA_String_Contents, idname);
    return TRUE;
}
*/

//--- Open a simple ASL file requster for texture loading
BOOL OpenASL (char *title, char *sdir, char *sname , char *filename, char *dir, char *name) {
    BOOL rep=FALSE;
    struct FileRequester *fr=NULL;
    // puts("In OpenASL");

    struct TagItem FRTags[] = { {ASL_Hail, (ULONG) title},
				{ASL_Dir, (ULONG) sdir},
				{ASL_File, (ULONG) sname},
				{TAG_DONE} };
    fr=AllocFileRequest();
    rep=(BOOL) AslRequest(fr,FRTags);
    // printf("rep=%d\n",rep);
    // puts ("ok");
    if (rep) {
	strcpy(name,fr->rf_File);
	strcpy(dir,fr->rf_Dir);
	strcpy(filename,fr->rf_Dir);
	AddPart(filename,name,255);
    };
    // printf("Load File Found:%s\n",filename);
    FreeFileRequest(fr);
    return rep;
}


/*-------------------------
  MISC CALLBACKS
--------------------------*/
void MenuCmd (Object *obj) {
    // puts("In SpecialCmd");
    ULONG store=0;
    BOOL rep=FALSE;
    char *objname=NULL;

    struct GLImage *glimage=NULL;

    if (obj==MyApp->MNAbout) {
	char temp[1000];
	sprintf(temp,"\033cGLArea Demo\n\n"
		     "Version 1.4 (" __DATE__ ")\n"
		     "Written by Bodmer Stephan [sbodmer@lsi-media.ch]\n\n"
		     "GLArea.mcc V%d.%d & ImageDB.mcc V%d.%d\n"
		     "are Copyright 2000 by LSI Media SàRL\n"
		     "[http://www.lsi-media.ch]\n\n"
		     "These classes are freeware for non-commercial use\n\n"
		     "ImageDB.mcc uses guigfx.library copyright by Timm S. Mueller\n\n"
		     "Pawn object created by Stephan Bielmann\n"
		     "OpenGL code generated by software with VRMLEditor\n",glarea_version,glarea_revision,imdb_version,imdb_revision);
	MUI_Request (MyApp->App,MyApp->WI_Main,0,"About","Ok",temp);
    }
    else if (obj==MyApp->MNAboutMUI) {
	 DoMethod((Object *) MyApp->App, MUIM_Application_AboutMUI, MyApp->WI_Main);
    }
    else if (obj==MyApp->MNOpen) {
	rep=OpenASL("Load an Image",dir,name,filename,dir,name);
	if (rep) {
	    char mini[255];

	    //--- Load the texture via ImageDB.mcc
	    glimage=DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_LoadImage, filename, name, 128, 128, MUIF_ImageDB_FlipY);
	    //--- create a Stamp version of the texure for display purpose
	    sprintf(mini,"%s_mini",name);
	    DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_ScaleImage, name, mini, 60, 40, 0);
	    DoMethod((Object *) MyApp->GLAR_SimpleAnimation, MUIM_GLArea_Redraw);

	    //--- retreive the pointer to the name of the image (needed to insert in the MUI listview)
	    //--- BTW it's the variable "name"
	    objname=(char *) DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_GetName, glimage);
	    DoMethod((Object *) MyApp->LV_Background, MUIM_List_InsertSingle, objname, MUIV_List_Insert_Bottom);
	    DoMethod((Object *) MyApp->LV_Ground, MUIM_List_InsertSingle, objname, MUIV_List_Insert_Bottom);
	    DoMethod((Object *) MyApp->LV_Texture, MUIM_List_InsertSingle, objname, MUIV_List_Insert_Bottom);

	};
    };
}

//--- Simple animation (left GLArea object) events
void SACmd (Object *obj) {
    ULONG store=0;

    if (obj==MyApp->CY_SAObject) {
	DoMethod((Object *) MyApp->GLAR_SimpleAnimation, MUIM_GLArea_Break);
	GetAttr(MUIA_Cycle_Active, (Object *) MyApp->CY_SAObject, &store);
	object=(int) store;
	DoMethod((Object *) MyApp->GLAR_SimpleAnimation, MUIM_GLArea_Redraw);
	DoMethod((Object *) MyApp->GLAR_MouseMove, MUIM_GLArea_Redraw);
    }
    else if (obj==MyApp->CY_SARendering) {
	DoMethod((Object *) MyApp->GLAR_SimpleAnimation, MUIM_GLArea_Break);
	GetAttr(MUIA_Cycle_Active, (Object *) MyApp->CY_SARendering, &store);
	rendering=(int) store;
	DoMethod((Object *) MyApp->GLAR_SimpleAnimation, MUIM_GLArea_Redraw);
	DoMethod((Object *) MyApp->GLAR_MouseMove, MUIM_GLArea_Redraw);
    }
    //--- Texture previews
    else if (obj==MyApp->LV_Background) {
	char mini[255];
	DoMethod((Object *) MyApp->LV_Background,MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &store);
	SetAttrs((Object *) MyApp->STR_PO_Background, MUIA_String_Contents, store);
	//--- Get the real texture
	backtex=(struct GLImage *) DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_GetImage, (char *) store);
	//--- Get the Stamp version
	sprintf(mini,"%s_mini",store);
	backimage=(struct GLImage *) DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_GetImage, mini);
	DoMethod((Object *) MyApp->GLAR_Background, MUIM_GLArea_Redraw);
    }
    else if (obj==MyApp->LV_Ground) {
	char mini[255];
	DoMethod((Object *) MyApp->LV_Ground,MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &store);
	SetAttrs((Object *) MyApp->STR_PO_Ground, MUIA_String_Contents, store);
	groundtex=(struct GLImage *) DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_GetImage, (char *) store);
	sprintf(mini,"%s_mini",store);
	groundimage=(struct GLImage *) DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_GetImage, mini);
	DoMethod((Object *) MyApp->GLAR_Ground, MUIM_GLArea_Redraw);
    }
    else if (obj==MyApp->LV_Texture) {
	char mini[255];
	DoMethod((Object *) MyApp->LV_Texture,MUIM_List_GetEntry, MUIV_List_GetEntry_Active, &store);
	SetAttrs((Object *) MyApp->STR_PO_Texture, MUIA_String_Contents, store);
	objtex=(struct GLImage *) DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_GetImage, (char *) store);
	sprintf(mini,"%s_mini",store);
	objimage=(struct GLImage *) DoMethod((Object *) MyApp->IMDB_ImageDataBase, MUIM_ImageDB_GetImage, mini);
	DoMethod((Object *) MyApp->GLAR_Texture, MUIM_GLArea_Redraw);
	DoMethod((Object *) MyApp->GLAR_MouseMove, MUIM_GLArea_Redraw);
    };
}

//--- Long rendering events
void LRCmd (Object *obj) {
    ULONG store=0;

    if (obj==MyApp->BT_LRStart) {
	//--- Set the drawing function
	SetAttrs((Object *) MyApp->GLAR_LongRendering, MUIA_GLArea_DrawFunc, DrawLongRendering);
	//--- Start drawing
	DoMethod((Object *) MyApp->GLAR_LongRendering, MUIM_GLArea_Init);
	DoMethod((Object *) MyApp->GLAR_LongRendering, MUIM_GLArea_Redraw);
	//--- Set drawing function to NULL to prevent automatic drawing when window is resized
	SetAttrs((Object *) MyApp->GLAR_LongRendering, MUIA_GLArea_DrawFunc, NULL);
    }
    else if (obj==MyApp->BT_LRBreak) {
	//--- Only works in Threaded mode ;^)
	DoMethod((Object *) MyApp->GLAR_LongRendering, MUIM_GLArea_Break);
    }
    else if (obj==MyApp->CH_LRThreaded) {
	GetAttr(MUIA_Selected, (Object *) MyApp->CH_LRThreaded, &store);
	SetAttrs((Object *) MyApp->GLAR_LongRendering, MUIA_GLArea_Threaded ,(BOOL) store);
    }
    else if (obj==MyApp->CH_LRBuffered) {
	GetAttr(MUIA_Selected, (Object *) MyApp->CH_LRBuffered, &store);
	DoMethod((Object *) MyApp->GLAR_LongRendering, MUIM_GLArea_Break);
	SetAttrs((Object *) MyApp->GLAR_LongRendering, MUIA_GLArea_Buffered, (BOOL) store);
	//--- I Need to destroy and recreate the GLContext when switching to non bufferer mode
	SetAttrs((Object *) MyApp->WI_Main, MUIA_Window_Open, FALSE);
	SetAttrs((Object *) MyApp->WI_Main, MUIA_Window_Open, TRUE);
	// DoMethod((Object *) MyApp->GLAR_LongRendering, MUIM_Hide);
	// DoMethod((Object *) MyApp->GLAR_LongRendering, MUIM_Show);
	// DoMethod((Object *) MyApp->GLAR_LongRendering, MUIM_GLArea_Redraw);
    };
}

/*
void FSCmd (Object *obj) {
    if (obj==MyApp->BT_FullScreen) {
	RenderScreen = OpenScreenTags (NULL,
					SA_DisplayID, (ULONG) displayid,
					SA_Depth, displaydepth,
					// SA_Type, PUBLICSCREEN,
					SA_SharePens,TRUE,
					// SA_Title, "OpenGL render Screen",
					TAG_DONE);
	SetAttrs((Object *) MyApp->WI_FullScreen, MUIA_Window_Screen, RenderScreen);
	SetAttrs((Object *) MyApp->WI_FullScreen, MUIA_Window_Width, RenderScreen->Width);
	SetAttrs((Object *) MyApp->WI_FullScreen, MUIA_Window_Height, RenderScreen->Height);
	SetAttrs((Object *) MyApp->WI_FullScreen, MUIA_Window_Open, TRUE);
    }
    else if (obj==MyApp->WI_FullScreen) {
	SetAttrs((Object *) MyApp->WI_FullScreen, MUIA_Window_Open, FALSE);
	CloseScreen (RenderScreen);
    };
}
*/
//------------------------------------------------------------------------------------------------
//-------------------------------------------MAIN PART--------------------------------------------
//------------------------------------------------------------------------------------------------

/*------------------
   Init functions
------------------*/
void StartUp() {
    //--- Get Workbench mode id
    // char idname[255];
    // struct Screen *wb=NULL;
    ULONG store=0;

    /*
    wb=LockPubScreen(NULL);
    displayid= GetVPModeID( &wb->ViewPort);
    displaydepth=wb->BitMap.Depth;
    UnlockPubScreen(NULL,wb);
    */

    //--- Check if ImageDB.mcc object is created
    if (MyApp->IMDB_ImageDataBase==NULL) {
	char temp[]={"If you want to have custom texture mapping enabled\n"
		     "you have to install ImageDB.mcc and guigfx.library !\n"};
	SetAttrs((Object *) MyApp->MNOpen, MUIA_Menuitem_Enabled, FALSE);
	SetAttrs((Object *) MyApp->PO_Background,MUIA_Disabled,TRUE);
	SetAttrs((Object *) MyApp->PO_Ground,MUIA_Disabled,TRUE);
	SetAttrs((Object *) MyApp->PO_Texture,MUIA_Disabled,TRUE);
	imdb_version=0;
	imdb_revision=0;
	MUI_Request (MyApp->App,MyApp->WI_Main,0,"About","Ok",temp);
    } else {
	GetAttr(MUIA_Version, (Object *) MyApp->IMDB_ImageDataBase,&imdb_version);
	GetAttr(MUIA_Revision, (Object *) MyApp->IMDB_ImageDataBase,&imdb_revision);
    };
    // ConvertDisplayID(idname,displayid);
    // SetAttrs((Object *) MyApp->STR_PA_ScreenMode, MUIA_String_Contents, idname);
    GetAttr(MUIA_Version, (Object *) MyApp->GLAR_SimpleAnimation,&glarea_version);
    GetAttr(MUIA_Revision, (Object *) MyApp->GLAR_SimpleAnimation,&glarea_revision);
}

void ClearAll() {
    if (MUIMasterBase) CloseLibrary(MUIMasterBase);
}

/*-----------------------------
  ------MAIN FUNCTIONS ---------
  -----------------------------*/
int main(int argc, char **argv) {
    ULONG sig=0,store;
    
    MUIMasterBase=(struct Library *) OpenLibrary ((UBYTE*)MUIMASTER_NAME,MUIMASTER_VLATEST);
    if (MUIMasterBase==NULL) {
	puts ("Can't open muimaster.library");
	ClearAll();
	return 1;
    };

    //---  Creation of MUI Application
    MyApp=CreateApp();
    if (MyApp) {
	StartUp();
	//-- Main loop
	while (DoMethod((Object *) MyApp->App,MUIM_Application_NewInput,&sig)!=MUIV_Application_ReturnID_Quit) {
	    if (sig) {
		sig = Wait(sig | SIGBREAKF_CTRL_C);
		if (sig & SIGBREAKF_CTRL_C) break;
	    };
	}; // end while
	DisposeApp(MyApp);
    }
    else {
	MUI_Request (NULL,NULL,0,"MUI Error","Ok","Can't create MUI Application!!!\n"
						  "Do you have installed GLArea.mcc ?");
    };
    ClearAll();
    return 0;
}

