// CROMSelector.cpp

#include <BeHeaders>

#include "Defines.h"
#include "CROMSelector.h"

#include "driver.h"

const float		kSelHeight	= 400;
const float		kSelWidth		= 250;
const float		kSelBorder	= 8;
const BPoint		kSelLeftTop	= BPoint(100, 50);

extern app_info		gAppInfo;

CROMSelector::CROMSelector()
	: BWindow(BRect(0, 0, kSelWidth, kSelHeight), "Select Game", B_TITLED_WINDOW, B_NOT_ZOOMABLE), mCancel(true)
{
	BButton		*cancelButton;
	BButton		*okButton;
	BScrollView	*aScrollView;
	BView		*aTopView;

	aTopView = new BView(Bounds(), "topview", B_FOLLOW_ALL_SIDES, B_WILL_DRAW);
	aTopView->SetViewColor(224, 224, 224);
	AddChild(aTopView);

	okButton = new BButton(BRect(0, 0, 0, 0), "OK", "OK", new BMessage(eWhat_OpenROM), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT);
	okButton->ResizeToPreferred();
	okButton->MoveTo(Bounds().right-okButton->Bounds().Width()-kSelBorder, Bounds().bottom-okButton->Bounds().Height()-kSelBorder);

	cancelButton = new BButton(BRect(0, 0, 0, 0), "Cancel", "Cancel", new BMessage(B_QUIT_REQUESTED), B_FOLLOW_BOTTOM | B_FOLLOW_RIGHT);
	cancelButton->ResizeToPreferred();
	cancelButton->MoveTo(okButton->Frame().left-cancelButton->Bounds().Width()-2*kSelBorder, Bounds().bottom-okButton->Bounds().Height()-kSelBorder);

	font_height aFontHeight;
	be_plain_font->GetHeight(&aFontHeight);
	BStringView* NrOfGames = new BStringView(BRect(kSelBorder, 0, Bounds().Width()-kSelBorder, 0.5*kSelBorder+aFontHeight.ascent+aFontHeight.descent), "NrOfGames", "", B_FOLLOW_RIGHT);
	NrOfGames->SetAlignment(B_ALIGN_RIGHT);
	aTopView->AddChild(NrOfGames);

	mGameList = new BListView(BRect(kSelBorder, NrOfGames->Frame().bottom+1, Bounds().Width()-kSelBorder-B_V_SCROLL_BAR_WIDTH, okButton->Frame().top-1.5*kSelBorder), "romList", B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES);
	aScrollView = new BScrollView("listScroll", mGameList, B_FOLLOW_ALL_SIDES, 0, false, true);
	BuildROMList();
	char buf[20];
	sprintf(buf, "%li Games", mGameList->CountItems());
	NrOfGames->SetText(buf);
	NrOfGames->SetHighColor(112, 112, 112);

	aTopView->AddChild(aScrollView);
	aTopView->AddChild(cancelButton);
	aTopView->AddChild(okButton);
	okButton->MakeDefault(true);
	mGameList->Select(0);
	mGameList->MakeFocus(true);
	if (mGameList->CountItems() == 0)  okButton->SetEnabled(false);

	SetSizeLimits(kSelWidth, kSelWidth*2, kSelWidth, kSelWidth*10);
	MoveTo(kSelLeftTop);
	Show();
}

CROMSelector::~CROMSelector()
{
}

void
CROMSelector::BuildROMList()
{
	BEntry		appEntry;
	BDirectory	romDir;

	appEntry.SetTo(&gAppInfo.ref);
	appEntry.GetParent(&appEntry);
	romDir.SetTo(&appEntry);
	if (romDir.SetTo(&romDir, "ROMS") == B_NO_ERROR) {
		BEntry	anEntry;
		
		romDir.Rewind();
		
		while (romDir.GetNextEntry(&anEntry, true) == B_NO_ERROR) {
			if (anEntry.IsDirectory()) {
				const GameDriver	*driverP;
				char				name[B_FILE_NAME_LENGTH];
								
				anEntry.GetName(name);
				
				if (driverP = GetDriverP(name))
					AddROMItem(driverP);
			}
		}
	}
}

const GameDriver *
CROMSelector::GetDriverP(
	const char		*inDirName)
{
	const GameDriver	*theDriverP = NULL, **driverPP = drivers;
	
	while (*driverPP) {
		if (strcmp((*driverPP)->name, inDirName) == 0)
			theDriverP = *driverPP;
		driverPP++;
	}
	
	return theDriverP;
}

void
CROMSelector::AddROMItem(
	const GameDriver	*inDriverP) 
{
	CROMItem	*newGame;

	newGame = new CROMItem(inDriverP->description, inDriverP->name);
	
	mGameList->AddItem(newGame);
}

void
CROMSelector::MessageReceived(
	BMessage	*inMessage)
{
	switch (inMessage->what) {
		case eWhat_OpenROM: {
				CROMItem* selected = (CROMItem*)mGameList->ItemAt(mGameList->CurrentSelection());
				if (selected != NULL) {
					BMessage	openMsg(eWhat_OpenROM);
					
					openMsg.AddString("argv", selected->ROMDir());
					be_app->PostMessage(&openMsg);
					mCancel = false;
				}
				PostMessage(B_QUIT_REQUESTED);
			}
			break;
			
		default:
			BWindow::MessageReceived(inMessage);
			break;
	}
}


bool CROMSelector::QuitRequested()
{
	if (mCancel) {
		be_app->PostMessage(eWhat_SelROMCancel);
		PostMessage(B_QUIT_REQUESTED);
	}
	return true;
}


#pragma mark class CROMItem

CROMItem::CROMItem(
	const char	*inGameDesc,
	const char	*inROMName) : BStringItem(inGameDesc)
{
	mROMStr = inROMName;
}
