/* indent:4  tabsize:8  font:fixed-width */

#import "ModuleList.h"

#define str_copy(str,zone) (( str== NULL) ? NULL : NXCopyStringBufferFromZone(str,zone))
			  
#define str_free(str)    {if (str) free(str);}

@implementation ModuleInfo


/*----------------------------------------------------------------------------
|
|    - initWithController:aController name:(const char *)aName \
|                                     path:(const char *)aPath
|
|    returns:  (id) self	OK
|	       (id) nil		Unable to initialize.
|
|-----------------------------------------------------------------------------
|
|    Designated initializer for ModuleInfo class.  
|			
\----------------------------------------------------------------------------*/

- initWithController:aController 
                name:(const char *)aName 
                path:(const char *)aPath
{
    char iconName[256];
	
	[super init];
    
    controller = aController;
    
    // get the bundle for this game
    if (aPath && strlen(aPath))
    {
        theBundle = [[NXBundle allocFromZone:[self zone]]
	                    initForDirectory:aPath];
	if (theBundle == nil)
	{
	    NXLogError("Unable to access bundle %s (%s)\n", aPath, aName);
	    [self free];
	    return nil;
        }
    }
    else
    {
		NXLogError("ModuleList:initWithView:name:path: -- invalid path\n");
		return nil;
    }
    
    realName = str_copy(aName, [self zone]);
    
    /* this lets you customize the name of the game using the 
       Localizable.strings file in the game bundle */
       
    gameName = str_copy(
		NXLoadLocalStringFromTableInBundle(NULL, theBundle, aName, NULL),
		[self zone]);
		
	// added by Trombino for module icon support
	sprintf(iconName, "%sIcon", realName);
	if([theBundle getPath:iconPath forResource:iconName ofType:"tiff"])
	{
		hasIcon = YES;
	}
	else
	{
		if([theBundle getPath:iconPath forResource:iconName ofType:"eps"])
		{
			hasIcon = YES;
		}
		else
		{
			hasIcon = NO;
		}
	}
	
    return self;
}


/*----------------------------------------------------------------------------
|
|    - setController:newController
|
|    returns:  (id) the old controller
|
|-----------------------------------------------------------------------------
|
|    Set the game controller.
|			
\----------------------------------------------------------------------------*/

- setController:newController
{
    id oldController = controller;
    controller = newController;
    return oldController;
}


/*----------------------------------------------------------------------------
|
|    - controller
|
|    returns:  (id) the controller
|
|-----------------------------------------------------------------------------
|
|    Return the game controller.
|			
\----------------------------------------------------------------------------*/

- controller
{    
    return controller;
}


/*----------------------------------------------------------------------------
|
|    - setFailed:(BOOL)flag
|
|    returns:  (id) self
|
|-----------------------------------------------------------------------------
|
|    Set the failed flag.  Turn on the failed flag when the module has failed
|    to load.
|			
\----------------------------------------------------------------------------*/

- setFailed:(BOOL)flag
{
    failed = flag;
    return self;
}


/*----------------------------------------------------------------------------
|
|    - (BOOL)failed
|
|    returns:  (BOOL) state of failed flag
|
|-----------------------------------------------------------------------------
|
|    Return the failed flag.
|			
\----------------------------------------------------------------------------*/

- (BOOL)failed
{
    return failed;
}


/*----------------------------------------------------------------------------
|
|    - (const char *) gameName
|
|    returns:  (const char *) the name of the game
|
|-----------------------------------------------------------------------------
|
|    Returns the name of this game module (localized).
|			
\----------------------------------------------------------------------------*/

- (const char *) gameName
{    
    return gameName;
}


/*----------------------------------------------------------------------------
|
|    - (const char *) realName
|
|    returns:  (const char *) the real name of the game
|
|-----------------------------------------------------------------------------
|
|    Returns the name of this game module (non-localized).
|			
\----------------------------------------------------------------------------*/

- (const char *) realName
{    
    return realName;
}


/*----------------------------------------------------------------------------
|
|    - (const char *) path
|
|    returns:  (const char *) the path of the module
|
|-----------------------------------------------------------------------------
|
|    Returns the path to this game module.
|			
\----------------------------------------------------------------------------*/

- (const char *) path
{    
    return [theBundle directory];
}


// Added by Trombino
- (char *)iconPath
{
	return iconPath;
}

- (BOOL)hasIcon
{
	return hasIcon;
}

/*----------------------------------------------------------------------------
|
|    - (NXBundle *)bundle
|
|    returns:  (NXBundle *) the bundle for the module
|
|-----------------------------------------------------------------------------
|
|    Returns an NXBundle corresponding to this game module.
|			
\----------------------------------------------------------------------------*/

- (NXBundle *)bundle
{    
    return theBundle;
}

/*----------------------------------------------------------------------------
|
|    - free
|
|    returns:  [super free]
|
|-----------------------------------------------------------------------------
|
|    Deallocate this object.
|			
\----------------------------------------------------------------------------*/

- free
{
    [controller free];
    str_free(gameName);
    str_free(realName);
    
    // NXBundles with dynamically loaded code can't be freed; this 
    // might be a problem, but I don't think so.
    [theBundle free];
    return [super free];
}

@end

/*===========================================================================*/


@implementation ModuleList

- (const char *) nameAt: (int) i
{
    return [[self objectAt: i] gameName];
}

- (const char *) realNameAt: (int) i
{
    return [[self objectAt: i] realName];
}

- controllerAt: (int) i
{
    return [[self objectAt: i] controller];
}

- (const char *)pathAt:(int)i
{
    return [[self objectAt:i] path];
}

static int docompare(const void *x, const void *y)
{
    return strcasecmp([(id)(*(ModuleInfo **)x) realName], 
                      [(id)(*(ModuleInfo **)y) realName]);
}

- sort
{
    qsort((ModuleInfo **)dataPtr, numElements, sizeof(id), docompare);
    return self;
}

@end
