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

#import "GameModule.h"
#import "GamePref.h"
#import "localstrings.h"

@implementation GameModule


/*---------------------------------------------------------------------------
|
|    - initFromBundle:aBundle
|
|    returns: (id) [super init]
|
|----------------------------------------------------------------------------
|
|    Instantiate an object of this class.
|			
\---------------------------------------------------------------------------*/

- initFromBundle:aBundle withName:(const char *)name
{
    char path[MAXPATHLEN+1];

    [super init];
    bundle = aBundle;
    gameName = NXCopyStringBufferFromZone(name, [self zone]);

    if ([bundle getPath:path forResource:"Engine.nib" ofType:NULL])
    {
	[NXApp loadNibFile:path 
		    owner:self
		withNames:NO 
		    fromZone:[self zone]];
    }
    [prefs setGameName:gameName];
    
    return self;
}


/*---------------------------------------------------------------------------
|
|    - inspector:sender
|
|    returns: (id) this module's inspector or nil
|
|----------------------------------------------------------------------------
|
|    Request by game engine to return inspector view.
|			
\----------------------------------------------------------------------------*/

- inspector:sender
{
    
    return inspector;
}


/*---------------------------------------------------------------------------
|
|    - inspectorWillBeRemoved
|
|    returns: (id) self
|
|----------------------------------------------------------------------------
|
|    Sent by game engine just before removing this module's inspector from
|    view.
|			
\----------------------------------------------------------------------------*/

- inspectorWillBeRemoved
{
    return self;
}

/*---------------------------------------------------------------------------
|
|    - inspectorInstalled
|
|    returns: (id) self
|
|----------------------------------------------------------------------------
|
|    Sent by game engine just after installing this module's inspector.
|			
\----------------------------------------------------------------------------*/

- inspectorInstalled
{
    return self;
}

/*---------------------------------------------------------------------------
|
|    - showRules:
|
|    returns: (id) self
|
|----------------------------------------------------------------------------
|
|    Display rules.
|			
\----------------------------------------------------------------------------*/

- showRules:sender
{
    if (!rulesWindow)
    {
        char path[MAXPATHLEN+1];
	
	if ([bundle getPath:path forResource:"Rules.nib" ofType:NULL])
	{
	    [NXApp loadNibFile:path 
			owner:self
		    withNames:NO 
			fromZone:[self zone]];
	}
	sprintf(path, "%sRules", gameName);
	[rulesWindow setFrameAutosaveName:path];
    }
    [rulesWindow makeKeyAndOrderFront:sender];
    return self;
}


/*---------------------------------------------------------------------------
|
|    - startGame:
|
|    returns:    (id)  self
|
|----------------------------------------------------------------------------
|
|    Start a new game.  This takes care of a lot of yucky details.  Always
|    invoke this if you subclass ([super startGame:]).
|			
\----------------------------------------------------------------------------*/

- startGame:sender
{
    [self commonGameSetup];
    return self;
}


/*---------------------------------------------------------------------------
|
|    - restartGame:
|
|    returns:  (id) self
|
|----------------------------------------------------------------------------
|
|    Restart the game in progress.  This takes care of a lot of yucky details.  
|    Always invoke this if you subclass ([super restartGame:]).
|			
\----------------------------------------------------------------------------*/

- restartGame:sender
{
    [self commonGameSetup];
    return self;
}


/*---------------------------------------------------------------------------
|
|    - endGame:sender
|
|    returns:  (id) self
|
|----------------------------------------------------------------------------
|
|    End the game in progress.  Discard the game window.
|			
\----------------------------------------------------------------------------*/

- endGame:sender
{
    if (gameWindow) [gameWindow performClose:self];
    if (rulesWindow) [rulesWindow performClose:self];
    return self;
}



/*---------------------------------------------------------------------------
|
|    - win
|
|     returns: (id) self
|
|----------------------------------------------------------------------------
|
|    Called when the game has been won.  Override to create new "win" 
|    behaviour.
|
\----------------------------------------------------------------------------*/

- win
{
    [SolEngine() win];
    return self;
}


/*---------------------------------------------------------------------------
|
|    - lose
|
|    returns: (id) self
|
|----------------------------------------------------------------------------
|
|    Called when the game has been lost.  Override to create new "lost"
|    behaviour.
|
\----------------------------------------------------------------------------*/

- lose
{
    return self;
}

/*---------------------------------------------------------------------------
|
|    - checkForWin
|
|    returns: (id) self
|
|----------------------------------------------------------------------------
|
|    Called to check the state of the game.
|
\----------------------------------------------------------------------------*/

- checkForWin
{
    return self;
}


/*----------------------------------------------------------------------------
|
|    - windowWillClose:sender
|
|    returns:  (id) self
|
|-----------------------------------------------------------------------------
|
|    Window delegate message.
|			
\----------------------------------------------------------------------------*/

- windowWillClose:sender
{
    if (sender == gameWindow)
    {
        gameWindow = nil;
        [sender setDelegate:nil];
    }
    return self;
}

/*----------------------------------------------------------------------------
|
|    - windowDidMove:
|
|    returns:  (id) self
|
|-----------------------------------------------------------------------------
|
|    Window delegate message.
|			
\----------------------------------------------------------------------------*/

- windowDidMove:sender
{
    if (sender == gameWindow)
    {
        [sender saveFrameUsingName:frameName];
    }
    return self;
}


/*----------------------------------------------------------------------------
|
|    - (BOOL) findPath:(char *)path forCardSize:(CardSize)cardSize 
|                                      realSize:(CardSize *)realSize
|
|    returns:  (BOOL)  YES if found
|                      NO  if not found
|
|-----------------------------------------------------------------------------
|
|    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'.
|			
\----------------------------------------------------------------------------*/

- (BOOL) findPath:(char *)path forCardSize:(CardSize)aCardSize
                                  realSize:(CardSize *)realSize
{
    const char *nibname;
    *realSize = aCardSize;
    
    if (aCardSize == CS_SMALL)
	nibname = "SmallGame.nib";
    else
	nibname = "LargeGame.nib";

    if (![bundle getPath:path forResource:nibname ofType:NULL])
    {
        if (aCardSize == CS_SMALL)
	{
	    nibname = "LargeGame.nib";
	    *realSize = CS_LARGE;
	}
	else
	{
	    nibname = "SmallGame.nib";
	    *realSize = CS_SMALL;
	}
	
	if (![bundle getPath:path forResource:nibname ofType:NULL])
        {
	    NXRunAlertPanel(gameName, LOCALIZED_NONIB_MSG, NULL, NULL,
	                    NULL);
	    return NO;
	}
    }
    return YES;
}


/*----------------------------------------------------------------------------
|
|    - loadGameWindow:(const char *)path ofSize:(CardSize)size
|
|    returns:  (id)  self
|
|-----------------------------------------------------------------------------
|
|    Load the specified NIB file containing the game window.
|
\----------------------------------------------------------------------------*/

- loadGameWindow:(const char *)path ofSize:(CardSize)size
{
    
    [NXApp loadNibFile:path 
                 owner:self
             withNames:NO 
	      fromZone:[self zone]];
	      
    sprintf(frameName, "%s%sWindow", gameName, 
                               (size == CS_SMALL) ? "Small" : "Large");
    [gameWindow setFrameUsingName:frameName];
    return self;
}

/*----------------------------------------------------------------------------
|
|    - commonGameSetup
|
|    returns:  (id)  self
|
|-----------------------------------------------------------------------------
|
|    HELPER METHOD: DO NOT OVERRIDE
|
|    Load the correct game NIB after rescanning generic preferences.
|
\----------------------------------------------------------------------------*/
- commonGameSetup
{
    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() returnCardSize];

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

    // load the preferred card size
    if ((cardSize != lastCardSize) || !gameWindow)
    {
	char path[MAXPATHLEN+1];
	CardSize realSize;

        if (![self findPath:path forCardSize:cardSize realSize:&realSize])
	{
	    NXRunAlertPanel(gameName, LOCALIZED_NIBGONE_MSG, NULL, NULL,
	                    NULL);
	    return self;
	}

        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() returnImageForSize:cardSize]];
	else
            [[SmallCard class] setCardBack:cardBack];
    }
    else{
    	if(cardBack == CS_CUSTOM)
	    [[Card class] setCardBackImage:[SolEngine() returnImageForSize: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]) == NX_DefaultDepth)
    {
        depth = [Window defaultDepthLimit];
    }
    if (depth != NX_TwoBitGrayDepth)
    {
        if (depth == NX_EightBitGrayDepth)
        {
            float grayLevel;
            NXConvertColorToGray(desktopColor, &grayLevel);
            [gameWindow setBackgroundGray:grayLevel];
        }
        else
        {
            [gameWindow setBackgroundColor:desktopColor];
        }
    }


    return self;
}


@end

