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

#import <Solitaire/GameModule.h>
#import <Solitaire/GamePref.h>
#import "localstrings.h"
#import <Solitaire/SmallCard.h>
#import <Solitaire/Card.h>


//static id _SolEngine;
#if 0
id SolEngine(void)
/*
 * called by game modules to get access to game engine
 */
{
    return nil; //_SolEngine;
}


void setSolEngine(id engine)
{
//    _SolEngine = engine;
}


id SolGameController(void)
/*
 * shortcut to current game controller
 */
{
    return [_SolEngine gameController];
}
#endif

@implementation GameModule

/*"
	GameModule is an abstract superclass providing a generic framework for 
	#{.solitaire} game modules.  It contains a number of methods which can be 
	overridden to provide game-specific behavior.

	The methods #startGame:, #restartGame:, and #checkForWin: should always be 
	overridden.
"*/


- initFromBundle:(NSBundle*)aBundle withName:(NSString*)name
/*"
	Designated initializer for the GameModule class.  If this method is 
	overridden in a subclass, always pass message back to this class via super.
"*/
{
    NSString* path;

    [super init];

    bundle = aBundle;
    gameName = [name copy];

    if (path = [bundle pathForResource:@"Engine" ofType:@"nib"])
    {
		[NSBundle loadNibFile:path externalNameTable:
			[NSDictionary dictionaryWithObjectsAndKeys:self, 
			@"NSOwner", nil] withZone:[self zone]];
    }
    [prefs setGameName:gameName];
    
    return self;
}


- (NSView*) inspector:sender
/*"
	Returns the module's inspector view.
"*/
{
    return inspector;
}


- (void) inspectorWillBeRemoved
/*"	
	Sent just before the module's inspector is removed; i.e. before switching 
	to a new game. The default implementation does nothing.
"*/
{
     
}


- (void) inspectorInstalled
/*"
	Sent immediately after this module's inspector view has been installed in
	the Game Selection Panel.  Override as needed. The default implementation
	does nothing.
"*/
{
     
}


- (void) showRules:(id)sender
/*"
	Displays the rules panel.
"*/
{
    if (!rulesWindow)
    {
        NSString* path;
	
	if (path = [bundle pathForResource:@"Rules" ofType:@"nib"])
	{
	    [NSBundle loadNibFile:path externalNameTable:
	    	[NSDictionary dictionaryWithObjectsAndKeys:self, 
		@"NSOwner", nil] withZone:[self zone]];
	}
	path = [NSString stringWithFormat:@"%@Rules",gameName];
	[rulesWindow setFrameAutosaveName:path];
    }
    [rulesWindow makeKeyAndOrderFront:sender]; 
}


- (void) startGame:(id)sender
/*"
	Start a new game; i.e. shuffle the deck and deal.  If overridden, always 
	send the message back to the GameModule class via super.
"*/
{
    [self commonGameSetup]; 
}


- (void) restartGame:(id)sender
/*"
	Sent when user selects "Restart Game" option.  The game should start over, 	
	without shuffling the deck.  If overridden, always send the message back to 
	the GameModule class via super.
"*/
{
    [self commonGameSetup]; 
}


- (void) endGame:(id)sender
/*"
	Sent when the game engine is about to switch to a different game.  Default 
	implementation hides the game window and rules window.
"*/
{
    if (gameWindow) [gameWindow performClose:self];
    if (rulesWindow) [rulesWindow performClose:self]; 
}


- (void) win
/*"
	Called when the game has been won.  By default, invokes the generic "win" 
	routine.  Override to create custom "game won" behaviour.
"*/
{
// This is currently declared in a category in the Solitaire app, though it 
// probably doesn't need to be since I moved SolEngine to the framework.
//    [SolEngine() win]; 
}


- (void) lose
/*"
	Called when the game has been lost.  Override to create new "lost" 
	behaviour.  Most games will not bother to detect losing situations.
"*/
{
     
}


- (void) checkForWin
/*"
	Determine if the game has been won.  Always override (unless your game is 
	impossible to win). If you determine that the game has been won, then
	call [self win].
"*/
{
    
}


- (BOOL) windowShouldClose:(id)sender
/*"
	If the closing window is the game window we set our outlet to
	nil and set it's delegate to nil too.
"*/
{
    if (sender == gameWindow)
    {
        gameWindow = nil;
        [sender setDelegate:nil];
    }
    return YES;
}


- (NSString*) nibPathForCardSize:(CardSize)aCardSize realSize:(CardSize *)realSize
/*"
	Attempt to find the NIB containing the indicated CardSize.  If not
	found, try to find *any* game NIB.  Returns the actual size found in
	'realSize'.
"*/
{
    NSString *path;
    NSString *nibname;
    *realSize = aCardSize;
    
    if (aCardSize == CS_SMALL)
	nibname = @"SmallGame";
    else
	nibname = @"LargeGame";

    if ((path = [bundle pathForResource:nibname ofType:@"nib"]) == nil)
    {
        if (aCardSize == CS_SMALL)
	{
	    nibname = @"LargeGame";
	    *realSize = CS_LARGE;
	}
	else
	{
	    nibname = @"SmallGame";
	    *realSize = CS_SMALL;
	}
	
	if ((path = [bundle pathForResource:nibname ofType:@"nib"]) == nil)
        {
	    NSRunAlertPanel(gameName,LOCALIZED_NONIB_MSG, @"", 
		nil, nil);
	    return nil;
	}
    }
    return path;
}


- (void) loadGameWindow:(NSString*)path ofSize:(CardSize)size
/*"
	Load the specified NIB file containing the game window.
"*/
{
    [NSBundle loadNibFile:path externalNameTable:
	[NSDictionary dictionaryWithObjectsAndKeys:self, @"NSOwner", nil] 
	withZone:[self zone]];

    frameName = [[NSString alloc] initWithFormat:@"%@%@Window",	gameName,                ((size == CS_SMALL) ? @"Small" : @"Large")];
    [gameWindow setFrameAutosaveName:frameName]; 
}


- (void) commonGameSetup
/*"
	HELPER METHOD. DO NOT OVERRIDE. We load the correct game nib after
	rescanning our generic preferences.
"*/
{
// This is currently declared in a categpry in the Soltiare app.
#if 0
    int depth;
    CardSize lastCardSize = cardSize;
    
    // if game only supports one size of card, don't bother trying to
    // load the missing size
    if (!ignoreSizePref)
        cardSize = [SolEngine() cardSize];

    // generic information used in all games
    desktopColor = [SolEngine() backgroundColor];
    cardBack = [SolEngine() cardBack];

    // load the preferred card size
    if ((cardSize != lastCardSize) || !gameWindow)
    {
        NSString* path = nil;
        CardSize realSize;

        if ((path = [self nibPathForCardSize:cardSize realSize:&realSize]) == nil)
          {
            NSRunAlertPanel(gameName,LOCALIZED_NIBGONE_MSG,
                            @"", nil, nil);
            return;
          }

        if (realSize != cardSize)
          {
            cardSize = realSize;
            ignoreSizePref = YES;
          }
        if (cardSize != lastCardSize || !gameWindow)
          {
            if (gameWindow) [gameWindow performClose:self];

            [self loadGameWindow:path ofSize:cardSize];
          }
    }  

    // Cards need to know what background to use
    if (cardSize == CS_SMALL){
    	if(cardBack == CS_CUSTOM)
	    [[SmallCard class] setCardBackImage:
		[SolEngine() imageForSize:cardSize]];
	else
            [[SmallCard class] setCardBack:cardBack];
    }
    else{
    	if(cardBack == CS_CUSTOM)
	    [[Card class] setCardBackImage:
		[SolEngine() imageForSize:cardSize]];
	else
            [[Card class] setCardBack:cardBack];
    }

    // Support added for a color background if using a 
    // color or 8-bit gray machine
    if ((depth = [gameWindow depthLimit]) == 0)
    {
        depth = [NSWindow defaultDepthLimit];
    }
    if (depth != NSBestDepth(NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
    {
        if (depth == NSBestDepth(NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
        {
            float grayLevel;
            [[desktopColor colorUsingColorSpaceName:NSCalibratedWhiteColorSpace] getWhite:&grayLevel alpha:NULL];
            [gameWindow setBackgroundColor:[NSColor colorWithCalibratedWhite:grayLevel alpha:1.0]];
        }
        else
        {
            [gameWindow setBackgroundColor:desktopColor];
        }
    }
#endif
}

@end

