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

#import "CardSet.h"
#import "SmallCard.h"

/*---------------------------------------------------------------------------
|
|    Card Globals
|
|    The arrays _CardPipPositions and _CardCardPips provide information about
|    the positioning of pips on cards.  There are 17 possible positions,
|    described in pipPositions, which are selectively refrerred to for each 
|    of 13 possible card values by a character string.
|
|    The letters A-Q are used to represent pips present in the given card.
|
|    The id's _CardFront, _CardBack etc... are images shared by all instances
|    of Card
|
\---------------------------------------------------------------------------*/

static NSPoint _CardPipPositions[] = {
    {13, 91}, {30, 91}, {47, 91},
    {30, 78},
    {30, 71},
    {13, 64}, {47, 64},
    {13, 52}, {30, 52}, {47, 52},
    {13, 39}, {47, 39},
    {30, 32},
    {30, 25},
    {13, 13}, {30, 13}, {47, 13}
};

extern char *_CardCardPips[];

// WARNING:  Because these static variables have the same names as static
//           variables in the superclass, override any methods that access
//           them.  The same goes for "_CardPipPositions" above.

static NSImage* _CardFrontImage = nil;
static NSImage* _CardBackImage = nil;
static NSImage* _CardSymbolsImage = nil;
static NSImage* _CardKingClubsImage = nil;
static NSImage* _CardKingDiamondsImage = nil;
static NSImage* _CardKingHeartsImage = nil;
static NSImage* _CardKingSpadesImage = nil;
static NSImage* _CardQueenClubsImage = nil;
static NSImage* _CardQueenDiamondsImage = nil;
static NSImage* _CardQueenHeartsImage = nil;
static NSImage* _CardQueenSpadesImage = nil;
static NSImage* _CardJackClubsImage = nil;
static NSImage* _CardJackDiamondsImage = nil;
static NSImage* _CardJackHeartsImage = nil;
static NSImage* _CardJackSpadesImage = nil;
static NSImage* _CardAceOfSpadesImage = nil;

static NSImage* _preDrawnImage[52];

static BOOL _preDrawnImagesAvailable;


@implementation SmallCard

/*"
	Instances of this class provide the same functionality as our superclass
	Card, except that they draw themselves more compactly. The only methods 
	that differ from our superclass are ones that are concerned with display.
"*/

//-------------------------------------------------------------------
//	Initializing the class
//-------------------------------------------------------------------

+ (void) initialize
/*"
   Initializes the class object. The partial card images from CardSet TIFFS
   are loaded here. 
"*/
{
    if (self == [SmallCard class])
    {
        NSBundle* bundle = [NSBundle bundleForClass:self];
        NSString* imagePath = nil;

        imagePath = [bundle pathForResource:@"sCard" ofType:@"tiff"];
        _CardFrontImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sBack" ofType:@"tiff"];
        _CardBackImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sKingClubs" ofType:@"tiff"];
        _CardKingClubsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sKingDiamonds" ofType:@"tiff"];
        _CardKingDiamondsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sKingHearts" ofType:@"tiff"];
        _CardKingHeartsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sKingSpades" ofType:@"tiff"];
        _CardKingSpadesImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sQueenClubs" ofType:@"tiff"];
        _CardQueenClubsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sQueenDiamonds" ofType:@"tiff"];
        _CardQueenDiamondsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sQueenHearts" ofType:@"tiff"];
        _CardQueenHeartsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sQueenSpades" ofType:@"tiff"];
        _CardQueenSpadesImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sJackClubs" ofType:@"tiff"];
        _CardJackClubsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sJackDiamonds" ofType:@"tiff"];
        _CardJackDiamondsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sJackHearts" ofType:@"tiff"];
        _CardJackHeartsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sJackSpades" ofType:@"tiff"];
        _CardJackSpadesImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sAceOfSpades" ofType:@"tiff"];
        _CardAceOfSpadesImage = [[NSImage alloc] initWithContentsOfFile:imagePath];

        imagePath = [bundle pathForResource:@"sSymbols" ofType:@"tiff"];
        _CardSymbolsImage = [[NSImage alloc] initWithContentsOfFile:imagePath];
    }
}


+ (void) drawCardImages
/*"
   Creates shared NSImage caches of all 52 cards in the deck. Uses the instance
   method #preDrawCards: to do the actual drawing.
"*/
{
    Card*	tempCard;
    int 	i,j;
    NSSize 	aSize;

    if(_preDrawnImagesAvailable) return;	// don't draw again
    aSize = [_CardFrontImage size];
    for(i=0; i<4; i++){
        for(j=0; j<13; j++){
            tempCard = [[SmallCard alloc] initSuit:i value:j faceUp:YES];
            _preDrawnImage[(i*13)+j] = [[NSImage alloc] initWithSize:aSize];
            [_preDrawnImage[(i*13)+j] addRepresentation:
                [[[NSCustomImageRep alloc] initWithDrawSelector:@selector(preDrawCard:) delegate:tempCard] autorelease]];
            [_preDrawnImage[(i*13)+j] lockFocus];
            [_preDrawnImage[(i*13)+j] unlockFocus];
            [tempCard release];
        }
    }
    _preDrawnImagesAvailable = YES;
    return;
}


+ (void) freeCardImages
/*"
   Frees the shared NSImage caches of all 52 cards.
"*/
{
    int i;

    if(!_preDrawnImagesAvailable) return;	// don't free again    
    for(i=0; i<52; i++){
    	[_preDrawnImage[i] release];
    }
    _preDrawnImagesAvailable = NO;
    return;
}


+ (void) setCardBackImage:theImage
/*"
   Sets a custom image used to draw the back of the card.
"*/
{
    if(theImage) {
		[_CardBackImage autorelease];
        _CardBackImage = [theImage copyWithZone:[self zone]];
    }
    return;
}


+ (void) setCardBack:(CardBack)aBack
/*"
   Sets the card back used to draw the back of the card.

   _{#{Constant	Image}}
   _{CS_DEFAULT	Original image from version 1.0.}
   _{CS_TRAD		Traditional pattern.}
   _{CS_SHIP		Ship at sea.}
   _{CS_CUSTOM	Custom image.}
"*/
{
    NSBundle* bundle = [NSBundle bundleForClass:self];
    NSString* imagePath = nil;

    switch (aBack)
    {
        case CS_DEFAULT:
            imagePath = [bundle pathForResource:@"sBack" ofType:@"tiff"];
            break;
        case CS_TRAD:
            imagePath = [bundle pathForResource:@"sTradBack" ofType:@"tiff"];
            break;
        case CS_SHIP:
            imagePath = [bundle pathForResource:@"sShip" ofType:@"tiff"];
            break;
        default:
            imagePath = [bundle pathForResource:@"sBack" ofType:@"tiff"];
            break;
    }
    
    if (imagePath != nil) {
        NSImage* newImage = [[NSImage alloc] initWithContentsOfFile:imagePath];
        if (newImage != nil) {
            [self setCardBackImage:newImage];
        }
    }
}


- (void) preDrawCard:(NSImage*)theImage
/*"
   Pre-draws theSharedNSImage, both outline and contents, by calling
   #drawOutlineAt: and #drawContentsAt: for point {0.0, 0.0}.
"*/
{
    NSPoint thePoint={0.,0.};
    
    [self drawOutlineAt:thePoint];
    [self drawContentsAt:thePoint];
}


- (void)drawCardAt:(NSPoint)thePoint
/*"
   Draws the card, both outline and contents, at thePoint, by calling
   #drawOutlineAt: and #drawContentsAt:. If the 52 cards of the deck have been
   pre-drawn, the shared NSImage cache is used. Otherwise, the card is drawn
   by compositing the partial images.
"*/
{
    if(_preDrawnImagesAvailable && faceUp){
    	[_preDrawnImage[(suit*13)+value] compositeToPoint:thePoint operation:NSCompositeSourceOver];
        return;
    }
    [self drawOutlineAt:thePoint];
    [self drawContentsAt:thePoint]; 
}


- (void) drawOutlineAt:(NSPoint)thePoint
/*"
   Draws the card's border at thePoint.
"*/
{
    [_CardFrontImage compositeToPoint:thePoint operation:NSCompositeSourceOver]; 
}


- (void) drawContentsAt:(NSPoint)thePoint
/*"
   Draws the contents of the card (but not the border) at thePoint.
"*/
{
    if (!faceUp)
    {
    
	/*------------------------------------------------------ 
	|
	|    Draw the back of the card
	|
	\------------------------------------------------------*/

        NSPoint destPoint = {thePoint.x + 6, thePoint.y + 5};

        [_CardBackImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
	
    } else {
    
	/*---------------------------------------------------------
	|
	|    Draw the upper left / lower right value indicator
	|
	\---------------------------------------------------------*/

        {
            NSRect sourceRect = {{value * 16, 60}, {8, 15}};
            NSPoint destPoint = {thePoint.x + 3, thePoint.y + 106};
			
            if (([self cardColor] == CS_RED)) {
                sourceRect.origin.x += 8;
            }
            [_CardSymbolsImage compositeToPoint:destPoint fromRect:sourceRect operation:NSCompositeSourceOver];
			
            sourceRect.origin.y -= 16;
            destPoint.x = thePoint.x + 69;
            destPoint.y = thePoint.y + 6;
			
            [_CardSymbolsImage compositeToPoint:destPoint fromRect:sourceRect		operation:NSCompositeSourceOver];
        }

	/*----------------------------------------------------------
	|
	|    Draw the upper left / lower right suit indicator
	|
	\----------------------------------------------------------*/

        {
            NSRect sourceRect = {{suit * 10, 10}, {10, 12}};
            NSPoint destPoint = {thePoint.x + 2, thePoint.y + 94};
			
	    [_CardSymbolsImage compositeToPoint:destPoint fromRect:sourceRect		operation:NSCompositeSourceOver];
        sourceRect.origin.x += 40;
        destPoint.x = thePoint.x + 69;
        destPoint.y = thePoint.y + 21;
	    [_CardSymbolsImage compositeToPoint:destPoint fromRect:sourceRect 	operation:NSCompositeSourceOver];
        }

	/*---------------------------------------------------------
	|
	|    Draw special card images for face cards and the
	|    ace of spades
	|
	\---------------------------------------------------------*/

        {
            NSPoint destPoint = {thePoint.x + 12, thePoint.y + 12};
    
	    switch (value)
	    {
            case CS_JACK:
                switch (suit) {
                    case CS_CLUBS:
                        [_CardJackClubsImage compositeToPoint:destPoint			operation:NSCompositeSourceOver];
                        break;
                    case CS_DIAMONDS:
                        [_CardJackDiamondsImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                        break;
                    case CS_HEARTS:
                        [_CardJackHeartsImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                        break;
                    case CS_SPADES:
                        [_CardJackSpadesImage compositeToPoint:destPoint				operation:NSCompositeSourceOver];
                        break;
                }
                return;

            case CS_QUEEN:
                switch (suit)
                  {
                    case CS_CLUBS:
                        [_CardQueenClubsImage compositeToPoint:destPoint                                                              operation:NSCompositeSourceOver];
                        break;
                    case CS_DIAMONDS:
                        [_CardQueenDiamondsImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                        break;
                        case CS_HEARTS:
                            [_CardQueenHeartsImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                            break;
                        case CS_SPADES:
                            [_CardQueenSpadesImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                            break;
                  }
                return;

            case CS_KING:
                switch (suit)
                    {
                    case CS_CLUBS:
                        [_CardKingClubsImage compositeToPoint:destPoint                                                             operation:NSCompositeSourceOver];
                        break;
                    case CS_DIAMONDS:
                        [_CardKingDiamondsImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                        break;
                    case CS_HEARTS:
                        [_CardKingHeartsImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                        break;
                    case CS_SPADES:
                        [_CardKingSpadesImage compositeToPoint:destPoint operation:NSCompositeSourceOver];
                        break;
                        }
                return;
		
            default:
                break;
        }
			
	    /*----------------------------------------------------
	    |
	    |    Not only draw the special image for the ace of
	    |    spades, but avoid the standard suit pip drawing
	    |
	    \----------------------------------------------------*/

	    if ((value == CS_ACE) && (suit == CS_SPADES))
        {
            [_CardAceOfSpadesImage compositeToPoint:destPoint			operation:NSCompositeSourceOver];
            return;
        }
        }
		
	/*------------------------------------------------------
	|
	|    Draw suit pips on the card based on patterns
	|    defined by the _CardCardSymbols and
	|    _CardCardPips arrays
	|
	\------------------------------------------------------*/

	{
        NSRect suitRect = {{suit * 20, 23}, {20, 21}};
        NSRect upsideSuitRect = {{80 + suit * 20, 23}, {20, 21}};
	    char *pipString = _CardCardPips[value];

	    while (*pipString)
	    {
            NSPoint tempPoint = _CardPipPositions[*pipString - 'A'];
            tempPoint.x += thePoint.x;
            tempPoint.y += thePoint.y;
            [_CardSymbolsImage compositeToPoint:tempPoint       			fromRect:(*pipString < 'K') ? suitRect : upsideSuitRect operation:NSCompositeSourceOver];
            pipString++;
	    }
    }
    }
}

@end

