//
// my_app.cc
//
#include <Application.h>
#include <Roster.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#include "my_app.h"
#include "CMameDisplay.h"
#include "my_sel.h"
#include "MessageConsts.h"

#include <storage/Path.h>
#include <storage/Entry.h>
#include <unistd.h>

extern "C" {
	/* Imported */
	extern int old_main(int argc, char **argv);
}

extern BJoystick*	GJoystick[];
volatile bool MameIsRunning = false;


my_app::my_app(): BApplication("application/x-vnd.BeMameTeam-BeMame"), mSelWin(NULL)
{
	// Code so you can run this from the Tracker and actually make the stuff work.
	// Set the current working directory to the directory with the executable.
	app_info	info;
	BEntry		entry;
	BPath		path;

	if (   (GetAppInfo(&info)		== B_OK)
		&& (entry.SetTo(&info.ref)	== B_OK)
		&& (path.SetTo(&entry)		== B_OK)
		&& (path.GetParent(&path)	== B_OK)
	){
		chdir(path.Path());
	} else {
		// If any of those fail, we should throw an exception or something.
	}
}



void my_app::ReadyToRun(void)
{
	BJoystick	joy;
	BJoystick*	njoy;
	// Init Joysticks
	char joyname[B_OS_NAME_LENGTH];
	for (int i=0; i<joy.CountDevices(); i++) {
		njoy = new BJoystick();
		if ((njoy->GetDeviceName(i, joyname) != B_OK) || (njoy->Open(joyname) == B_ERROR)) {
			delete njoy;
		} else {
			mJoystick.AddItem(njoy);
			mJoystickName.AddItem(new BString(joyname));
		}
	}
	// Start
	if (mStartArgs.IsEmpty()) {		// no commandline arguments
		mSelWin = new CSelWin();
	} else {						// we have commandline arguments
		for (int n=0; n<4; n++)  GJoystick[n] = (BJoystick*)mJoystick.ItemAt(n);
		PostMessage(&mStartArgs);
	}
}


void my_app::MessageReceived(BMessage* inMsg)
{
	switch (inMsg->what) {
		case MSGW_GAME_STOPPED: {
			if (mSelWin == NULL)
				PostMessage(B_QUIT_REQUESTED);
		} break;

		case MSGW_ARGS: {
			type_code	type;
			int32		cnt;
			if (   (MameIsRunning							== false)
				&& (inMsg->GetInfo(MSGN_ARGS, &type, &cnt)	== B_OK)
				&& (type									== B_STRING_TYPE))
			{
				MameIsRunning = true;
				mMameThreadId = spawn_thread(ThreadEntry, "MAME_main_thread", B_DISPLAY_PRIORITY, new BMessage(*inMsg));
				resume_thread(mMameThreadId);
			}
		} break;
		
		default: {
			BApplication::MessageReceived(inMsg);
		} break;
	}
}


void my_app::ArgvReceived(int32 inArgc, char** inArgv)
{
	mStartArgs.what = MSGW_ARGS;
	for (int32 i=0; i<inArgc; i++) {
		mStartArgs.AddString(MSGN_ARGS, inArgv[i]);
	}
}


long my_app::ThreadEntry(void* msgPtr)
{
	BMessage*	msg = (BMessage*)msgPtr;
	type_code	type;
	int32		argc;

	if ((msg->GetInfo(MSGN_ARGS, &type, &argc) == B_OK) && (type == B_STRING_TYPE)) {
		char** argv;
		const char* arg;

		argv = new char* [argc];
		for (int32 idx=0; idx<argc; idx++) {
			if (msg->FindString(MSGN_ARGS, idx, &arg) != B_OK)  arg = " ";
			argv[idx] = new char[strlen(arg)+1];
			sprintf(argv[idx], arg);
			printf("Argument %li: '%s'\n", idx, arg);
		}
		old_main(argc, argv);
		if (gDisplay != NULL)
			gDisplay->ShutDown();
		for (int32 i=0; i<argc; i++)  delete [] argv[i];
		delete [] argv;
		be_app->PostMessage(MSGW_GAME_STOPPED);
	}
	delete msg;
	MameIsRunning = false;
	return 0;
}

