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

#import "Solitaire.h"
#import "ModuleList.h"
#import "localstrings.h"

#include <sys/dir.h>

#define GAMEDIRECTORY	"/LocalLibrary/Solitaire"

@implementation Solitaire(More)

/*----------------------------------------------------------------------------
|
|    - getGameType
|
|    returns:  (id) self
|
|-----------------------------------------------------------------------------
|
|    Go find dynamically loadable Solitaire games in ~/Library/Solitaire,
|    Solitaire.app, and /LocalLibrary/Solitaire.  Load their descriptions
|    into the game-selection browser.
|			
\----------------------------------------------------------------------------*/

- getGameType
{
    id theMatrix;
    char buf[MAXPATHLEN+1];
    
    strcpy(buf, NXHomeDirectory());
    strcat(buf, "/Library/Solitaire");

    if (!moduleList)
    {
        moduleList = [[ModuleList allocFromZone:[self zone]] init];
    }
    
    [self loadGamesFrom:buf];
    [self loadGamesFrom:[self appDirectory]];
    [self loadGamesFrom:GAMEDIRECTORY];

    if ([moduleList count] == 0)
    {
        NXRunAlertPanel([NXApp appName], LOCALIZED_NOGAMES, 
	                                 LOCALIZED_TERMINATE, NULL, NULL);
	[NXApp terminate:self];
    }
    
    [moduleList sort];
    browserValid = NO;
    [gameSelectionBrowser loadColumnZero];
    theMatrix = [gameSelectionBrowser matrixInColumn:0];
    [theMatrix selectCellAt:realGameIndex:0];
    [theMatrix scrollCellToVisible:realGameIndex:0];
    
    return self;
}


/*----------------------------------------------------------------------------
|
|    - setGameType:(const char *)filename dir:(const char *)dirname
|
|    returns:  (id) self
|
|-----------------------------------------------------------------------------
|
|    Load the description of the specified .solitaire bundle into the 
|    browser.
|			
\----------------------------------------------------------------------------*/

- setGameType:(const char *)filename dir:(const char *)dirname
{
    id theMatrix;

    if (!moduleList)
    {
        moduleList = [[ModuleList allocFromZone:[self zone]] init];
    }

    browserValid = NO;
    [self addGameToList:filename dir:dirname];
    [moduleList sort];
    [gameSelectionBrowser loadColumnZero];
    theMatrix = [gameSelectionBrowser matrixInColumn:0];
    [theMatrix selectCellAt:realGameIndex:0];
    [theMatrix scrollCellToVisible:realGameIndex:0];

    return self;
}

/*----------------------------------------------------------------------------
|
|    - loadGamesFrom:(const char *)dirname
|
|    returns:  (id) self
|
|-----------------------------------------------------------------------------
|
|    Find all .solitaire modules in the specified directory.
|    If we find a module in several places, we keep only the first one found.
|			
\----------------------------------------------------------------------------*/

- loadGamesFrom:(const char *)dirname
{
    DIR *dir;
    struct direct *de;

    dir = opendir(dirname);
    if (dir == NULL) {
        return self;
    }

    while ((de = readdir(dir)) != NULL)
    {
    
        // Ignore '.'-files (not really necessary, I guess)
        if (de->d_name[0] == '.')
            continue;

        if (de->d_namlen > 10 && 
                !strcmp(&de->d_name[de->d_namlen-10], ".solitaire"))
        {
            [self addGameToList:de->d_name dir:dirname];
        }
    }

    closedir(dir);
    return self;
}

/*----------------------------------------------------------------------------
|
|    - addGameToList:(const char *)filename dir:(const char *)dirname
|
|    returns:  (id) self
|
|-----------------------------------------------------------------------------
|
|    Add the specified game to the list of games.
|
\----------------------------------------------------------------------------*/

- addGameToList:(const char *)filename dir:(const char *)dirname
{
    ModuleInfo *m;
    int i, numstrings;
    char name[60];
    BOOL valid = YES;
    char path[MAXPATHLEN];
    char *iptr;
   
    numstrings = [moduleList count];
    strcpy(name, filename);

    // Smash out the '.' in "Game.solitaire"
    if (iptr = rindex(name, '.'))
	*iptr = '\0';

    // check for duplicate modules; keep only the first one found
    for (i=0; (i < numstrings) && (valid == YES); i++)
    {
	if (!strcmp(name, [moduleList nameAt:i]))
	{
	    // already have a module with this name
	    valid = NO;
	}
    }
    
    if (valid) 
    {
	// add a new entry for this module
	sprintf(path, "%s/%s", dirname, filename);
	m = [[ModuleInfo allocFromZone:[self zone]]
	    initWithController:NULL name:name path:path];
	if (m)
	    [moduleList addObject:m];
    }
    return self;
}


/*----------------------------------------------------------------------------
|
|    - (const char *)appDirectory
|
|    returns:  (const char *) full path of main bundle
|
|-----------------------------------------------------------------------------
|
|    Returns the application's main bundle directory.
|			
\----------------------------------------------------------------------------*/

- (const char *)appDirectory
{
    return [[NXBundle mainBundle] directory];
}


@end
