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

#import "Klondike.h"
#import "localstrings.h"
#import "KlondikePrefs.h"
#import "DrawPileDelegate.h"
#import "GamePileDelegate.h"
#import "SuitPileDelegate.h"
#import "DiscardPileDelegate.h"

static id _klondikeSharedInstance = nil;


@implementation Klondike

+ (Klondike*) sharedInstance
/*"
 Instead of the old method of calling SolGameController when
 you wanted to message the Klondike game module, you now
 call [Klondike sharedInstance] and direct messages to
 the returned instance. You can use this to check if the game
 has been won, among other things.
"*/
{
    return _klondikeSharedInstance;
}

- initFromBundle:(NSBundle*)aBundle withName:(NSString*)name
/*"
 Extends our superclass method in order to set our shared
 instance variable.
"*/
{
    [super initFromBundle:aBundle withName:name];

    // This is used instead of having a global SolGameController()
    // function. It is assumed that this method will be called
    // only once and that our +sharedInstance method will return
    // the single instance.
    _klondikeSharedInstance = self;
    
    return self;
}


/*---------------------------------------------------------------------------
|
|    - startGame:
|
|----------------------------------------------------------------------------
|
|    Start a new game.
|			
\----------------------------------------------------------------------------*/

- (void) startGame:sender
{
    [super startGame:sender];
    [self setupGame:YES];
}


/*---------------------------------------------------------------------------
|
|    - restartGame:
|
|----------------------------------------------------------------------------
|
|    Restart the game in progress (i.e. don't shuffle the cards).
|			
\----------------------------------------------------------------------------*/

- (void) restartGame:sender
{
    [super restartGame:sender];
    [self setupGame:NO];    
}


/*---------------------------------------------------------------------------
|
|    - setupGame:(BOOL)redeal
|
|----------------------------------------------------------------------------
|
|    Setup a new game.  If "redeal" is true, deal a new deck, otherwise
|    use the same cards as the previous game.
|			
\----------------------------------------------------------------------------*/

- (void) setupGame:(BOOL)redeal
{
    int 			pileIndex, cardIndex , i;
    CardPileView*  	suitCardPiles[4];
    CardPileView*  	gameCardPiles[7];
    CardPile*  		drawCardPile;

    [gameWindow disableFlushWindow];

    [drawPileDelegate setDrawCardCount:[(KlondikePrefs*)prefs cardsToDraw]];
    [discardPileDelegate setDrawCardCount:[(KlondikePrefs*)prefs cardsToDraw]];
    
    //----------------------------------------------------------------
    //    Sync pile id's with current game window and set 
    //    preferences and delegates
    //----------------------------------------------------------------
    
    suitCardPiles[0] = suitPileView1;
    suitCardPiles[1] = suitPileView2;
    suitCardPiles[2] = suitPileView3;
    suitCardPiles[3] = suitPileView4;
    for (i = 0; i < 4; i++)
    {
        [suitCardPiles[i] setBackgroundColor:desktopColor];
        [suitCardPiles[i] setCardSize:cardSize];
        [suitCardPiles[i] setDelegate:suitPileDelegate];
    }
    
    gameCardPiles[0] = gamePileView1;
    gameCardPiles[1] = gamePileView2;
    gameCardPiles[2] = gamePileView3;
    gameCardPiles[3] = gamePileView4;
    gameCardPiles[4] = gamePileView5;
    gameCardPiles[5] = gamePileView6;
    gameCardPiles[6] = gamePileView7;
    for (i = 0; i < 7; i++)
    {
        [gameCardPiles[i] setBackgroundColor:desktopColor];
        [gameCardPiles[i] setCardSize:cardSize];
        [gameCardPiles[i] setDelegate:gamePileDelegate];
    }
    
    [gamePileDelegate setSuitCardPileViews:suitCardPiles];
    
    [drawPileView setBackgroundColor:desktopColor];
    [drawPileView setCardSize:cardSize];
    drawCardPile = [drawPileView cardPile];
    [drawPileDelegate setDiscardCardPileView:discardPileView];
    [drawPileView setDelegate:drawPileDelegate];
    
    [discardPileView setBackgroundColor:desktopColor];
    [discardPileView setCardSize:cardSize];
    [discardPileView setDelegate:discardPileDelegate];
    [discardPileDelegate setSuitCardPileViews:suitCardPiles];

    [gameWindow display];
    [gameWindow enableFlushWindow];
    [gameWindow flushWindow];


    //-----------------------------------------------------------------------
    //    Empty the recycle pile
    //-----------------------------------------------------------------------
    
    [recycleCardPile empty];

    //-----------------------------------------------------------------------
    //    Initialize the drawPileView to have a shuffled
    //    deck
    //-----------------------------------------------------------------------
    [drawCardPile empty];
    if (redeal)
    {
        [drawCardPile addDeck];
        [drawCardPile shuffle];
	
	// make a copy of the CardPile for restart option
	if (!prevDeck)
	{
	    prevDeck = [[CardPile allocWithZone:[self zone]]
	                           initForCardSize:cardSize];
	}
	else
	{
	    [prevDeck empty];
	    [prevDeck setCardSize:cardSize];
	}
    [prevDeck addCopyOfPile:drawCardPile];
    }
    else
    {
        if (prevDeck)
	{
	    // copy the saved deck back to the game deck
	    [prevDeck setCardSize:cardSize];
	    [drawCardPile addCopyOfPile:prevDeck];
	}
	else
	{
	    // this shouldn't happen, but just in case...
	    [drawCardPile empty];
	    [drawCardPile addDeck];
	    [drawCardPile shuffle];
	}
    }

    
    //----------------------------------------------------------------------
    //    Initialize the discardPileView as empty
    //----------------------------------------------------------------------

    [[discardPileView cardPile] empty];
    [discardPileView display];

    //-----------------------------------------------------------------------
    //    Initialize the four "suit piles" as empty
    //-----------------------------------------------------------------------

    for (pileIndex = 0; pileIndex < 4; pileIndex++)
    {
        [[suitCardPiles[pileIndex] cardPile] empty];
        [suitCardPiles[pileIndex] display];
    }

    //-----------------------------------------------------------------------
    //    Initialize and deal cards to the seven "user piles"
    //-----------------------------------------------------------------------

    for (pileIndex = 0; pileIndex < 7; pileIndex++)
    {
        CardPile* userPile = [gameCardPiles[pileIndex] cardPile];
        
        [userPile empty];
        [gameCardPiles[pileIndex] display];
    }

    for (pileIndex = 0; pileIndex < 7; pileIndex++)
    {
        CardPile* userPile = [gameCardPiles[pileIndex] cardPile];
        
        for (cardIndex = 0; cardIndex <= pileIndex; cardIndex++)
        {
            Card* tempCard = [drawCardPile dealTopCard];

            [userPile insertCard:tempCard at:CS_TOP];
            [gameCardPiles[pileIndex] display];
        }
        [[userPile topCard] flip];
        [gameCardPiles[pileIndex] display];
    }

    //-----------------------------------------------------------------------
    //    Draw the remaining cards on the
    //    drawPileView
    //-----------------------------------------------------------------------

    //[drawPileView display];
    
    [gameWindow display];

    [gameWindow makeKeyAndOrderFront:self]; 
}


/*---------------------------------------------------------------------------
|
|    - endGame:sender
|
|----------------------------------------------------------------------------
|
|    End the game in progress.  Discard the game window.
|			
\----------------------------------------------------------------------------*/

- (void) endGame:sender
{
    [super endGame:sender];

    // ****custom code here****
}


/*---------------------------------------------------------------------------
|
|    - checkForWin
|
|----------------------------------------------------------------------------
|
|    Called to check the state of the game.
|
\----------------------------------------------------------------------------*/

- (void) checkForWin
{
    if ([[suitPileView1 cardPile] cardCount] +
            [[suitPileView2 cardPile] cardCount] +
            [[suitPileView3 cardPile] cardCount] +
            [[suitPileView4 cardPile] cardCount] == 52)
    {
    	[self win];
    }
}

@end

