//
// $Id: Token.m,v 1.7 1997/10/31 04:52:10 nygard Exp $
//

//
//  This file is a part of Empire, a game of exploration and conquest.
//  Copyright (C) 1996  Steve Nygard
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//  You may contact the author by:
//     e-mail:  nygard@telusplanet.net
//

#import "Empire.h"

RCSID ("$Id: Token.m,v 1.7 1997/10/31 04:52:10 nygard Exp $");

#import "Token.h"

static NSColor *player_color[4];
static NSImage *player_icon_images[4][13];

static NSImage *terrain_images[3];
static NSImage *icon_masks[13];
static NSImage *icon_borders[13];

static NSImage *army_innards;
static NSImage *transport2_innards;
static NSImage *hovercraft_innards;

static NSImage *oddball_images[4][2];

struct image_names
{
    NSString *i_name;
    NSImage **i_image;
};

static struct image_names class_images[] =
{
    { @"unknown.tiff", &terrain_images[t_unknown] },
    { @"land.tiff", &terrain_images[t_land] },
    { @"water.tiff", &terrain_images[t_water] },

    { @"city_mask.tiff", &icon_masks[0] },
    { @"army_mask.tiff", &icon_masks[1] },
    { @"sentry_mask.tiff", &icon_masks[2] },
    { @"fighter_mask.tiff", &icon_masks[3] },
    { @"transport1_mask.tiff", &icon_masks[4] },
    { @"transport2_mask.tiff", &icon_masks[5] },
    { @"submarine_mask.tiff", &icon_masks[6] },
    { @"destroyer_mask.tiff", &icon_masks[7] },
    { @"cruiser_mask.tiff", &icon_masks[8] },
    { @"carrier1_mask.tiff", &icon_masks[9] },
    { @"carrier2_mask.tiff", &icon_masks[10] },
    { @"battleship_mask.tiff", &icon_masks[11] },
    { @"hovercraft_mask.tiff", &icon_masks[12] },

    { @"army_border.tiff", &icon_borders[1] },
    { @"sentry_border.tiff", &icon_borders[2] },
    { @"fighter_border.tiff", &icon_borders[3] },
    { @"transport1_border.tiff", &icon_borders[4] },
    { @"transport2_border.tiff", &icon_borders[5] },
    { @"submarine_border.tiff", &icon_borders[6] },
    { @"destroyer_border.tiff", &icon_borders[7] },
    { @"cruiser_border.tiff", &icon_borders[8] },
    { @"carrier1_border.tiff", &icon_borders[9] },
    { @"carrier2_border.tiff", &icon_borders[10] },
    { @"battleship_border.tiff", &icon_borders[11] },
    { @"hovercraft_border.tiff", &icon_borders[12] },

    { @"army_innards.tiff", &army_innards },
    { @"transport2_innards.tiff", &transport2_innards },
    { @"hovercraft_innards.tiff", &hovercraft_innards },
};
  
//======================================================================
// This class was required when the images were used in a browser or table
// view, since they made a copy of the image and wouldn't get updates
// to the player colors of the images.  Instead of initializing the
// images from data, we provide a method to redraw the image.
//
// The actual tokens are built up from a mask that is used to select
// the colored portion, and possibly an "innards" image, which is a
// part of the final image that should remain black.  (For example,
// the bits within the tracks of the Army image.
//
// The final image is composited over the background terrain image.  If
// the background terrain is a city, a black border is also composited
// around the unit icon to enhance visibility.  (I think I'm using
// about 50% alpha to darken the city.)
//======================================================================

#define Token_VERSION 1

@implementation Token

+ (void) initialize
{
    if (self == [Token class])
    {
        [self setVersion:Token_VERSION];

        if ([NSBundle bundleForClass:self] == nil)
        {
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                  selector:@selector (loadClassImages)
                                                  name:NSApplicationDidFinishLaunchingNotification
                                                  object:NSApp];
        }
        else
        {
            [self loadClassImages];
        }
    }
}

//----------------------------------------------------------------------

+ (void) loadClassImages
{
    int l;
    Player p;
    NSBundle *thisBundle;
    NSString *imagePath;

    thisBundle = [NSBundle bundleForClass:self];
    NSAssert (thisBundle != nil, @"Could not get bundle.");

    // load class images
    for (l = 0; l < sizeof (class_images) / sizeof (struct image_names); l++)
    {
        imagePath = [thisBundle pathForImageResource:class_images[l].i_name];
        NSAssert1 (imagePath != nil, @"Could not find image: '%@'", class_images[l].i_name);

        *(class_images[l].i_image) = [[NSImage alloc] initByReferencingFile:imagePath];
        NSAssert1 (*(class_images[l].i_image) != nil, @"Couldn't load image: '%@'\n", class_images[l].i_name);
    }

    for (p = p_neutral; p <= p_player3; p++)
    {
        for (l = 0; l < 13; l++)
            player_icon_images[p][l] = [icon_masks[0] copyWithZone:[self zone]];
        for (l = 0; l < 2; l++)
            oddball_images[p][l] = [icon_masks[0] copyWithZone:[self zone]];
    }

    [Token setColor:[NSColor lightGrayColor] forPlayer:p_neutral];
    [Token setColor:[NSColor colorWithCalibratedRed:34 / 255.0 green:255 / 255.0 blue:248 / 255.0 alpha:1.0]
           forPlayer:p_player1];
    [Token setColor:[NSColor colorWithCalibratedRed:255 / 255.0 green:26 / 255.0 blue:6 / 255.0 alpha:1.0]
           forPlayer:p_player2];
    [Token setColor:[NSColor colorWithCalibratedRed:243 / 255.0 green:255 / 255.0 blue:0 / 255.0 alpha:1.0]
           forPlayer:p_player3];

    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

//----------------------------------------------------------------------

+ (NSColor *) colorForPlayer:(Player)aPlayer
{
    return player_color[aPlayer];
}

//----------------------------------------------------------------------

+ (void) setColor:(NSColor *)aColor forPlayer:(Player)aPlayer
{
    player_color[aPlayer] = [aColor retain];

    [self rebuildIconsForPlayer:aPlayer];

    // Then invalidate the images...
}

//----------------------------------------------------------------------

+ (void) rebuildIconsForPlayer:(Player)aPlayer
{
    int l;
    NSRect aRect;
    NSPoint origin;

    origin = NSMakePoint (0, 0);
    aRect = NSMakeRect (0, 0, 16, 16);
  
    for (l = i_army; l <= i_hovercraft; l++)
    {
        [player_icon_images[aPlayer][l] lockFocus];

        [player_color[aPlayer] set];
        NSRectFill (aRect);
        [icon_masks[l] compositeToPoint:origin operation:NSCompositeDestinationIn];

        if (l == i_army)
            [army_innards compositeToPoint:origin operation:NSCompositeSourceOver];
        else if (l == i_loaded_transport)
            [transport2_innards compositeToPoint:origin operation:NSCompositeSourceOver];
        else if (l == i_hovercraft)
            [hovercraft_innards compositeToPoint:origin operation:NSCompositeSourceOver];
    
        [player_icon_images[aPlayer][l] unlockFocus];
    }

    [player_icon_images[aPlayer][0] lockFocus];

    [player_color[aPlayer] set];
    aRect = NSMakeRect (0, 0, 16, 16);
    NSRectFill (aRect);

    [icon_masks[0] compositeToPoint:origin operation:NSCompositeSourceOver];
    [player_icon_images[aPlayer][0] unlockFocus];

    [oddball_images[aPlayer][0] lockFocus];
    PSsetgray (NSBlack);
    NSRectFill (aRect);
    [player_icon_images[aPlayer][i_army] compositeToPoint:origin operation:NSCompositeSourceOver];
    [oddball_images[aPlayer][0] unlockFocus];

    [oddball_images[aPlayer][1] lockFocus];
    PSsetgray (NSBlack);
    NSRectFill (aRect);
    [player_icon_images[aPlayer][i_fighter] compositeToPoint:origin operation:NSCompositeSourceOver];
    [oddball_images[aPlayer][1] unlockFocus];
}

//----------------------------------------------------------------------

+ (NSImage **) oddballsForPlayer:(Player)aPlayer
{
    return oddball_images[aPlayer];
}

//----------------------------------------------------------------------

+ (NSImage **) iconBorders
{
    return icon_borders;
}

//======================================================================

- initIcon:(Icon)anIcon onTerrain:(Terrain)someTerrain forPlayer:(Player)aPlayer
{
    NSSize tokenSize;

    [super init];

    player = aPlayer;
    icon = anIcon;
    terrain = someTerrain;

    tokenSize = NSMakeSize (16, 16);
    tokenImage = [[NSImage alloc] initWithSize:tokenSize];
    NSAssert (tokenImage != nil, @"tokenImage is nil");

    [tokenImage addRepresentation:[[[NSCustomImageRep alloc] initWithDrawSelector:@selector (drawToken:) delegate:self]
                                       autorelease]];

    return self;
}

//----------------------------------------------------------------------

- (void) dealloc
{
    SNRelease (tokenImage);
  
    [super dealloc];
}

//----------------------------------------------------------------------

- (void) drawToken:(NSCustomImageRep *)imageRep
{
    NSPoint origin = {0, 0};

    //last_color_used = player_color[player];

    if (terrain == t_unknown || terrain == t_land || terrain == t_water)
    {
        [terrain_images[terrain] compositeToPoint:origin operation:NSCompositeSourceOver];
    }
    else
    {
        [player_icon_images[player][i_none] compositeToPoint:origin operation:NSCompositeSourceOver];
    }

    if (icon != i_none)
    {
        if (terrain == t_city)
        {
            [[NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:0.5] set];
            PScompositerect (0, 0, 16, 16, NSCompositeSourceOver);
        }

        [player_icon_images[player][icon] compositeToPoint:origin operation:NSCompositeSourceOver];

        if (terrain == t_city)
            [icon_borders[icon] compositeToPoint:origin operation:NSCompositeSourceOver];
    } 
}

//----------------------------------------------------------------------

- (NSImage *) tokenImage
{
#if 0
    if ([last_color_used isEqual:player_color[player]] == NO)
        [tokenImage recache];
#endif  
    return tokenImage;
}

@end
