//
//  Combat.m
//  longspear
//
//  Created by Niko Matsakis on Fri Jun 11 2004.
//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
//

#import "Combat.h"
#import "Actions.h"
#import "Entity.h"

@implementation Combat

- initWithCampaign:(Campaign*)camp name:(NSString*)name target:target
{
    if ((self = [super init])) {
        _name = [name retain];
        _comments = [[[NSDate date] description] retain];
        
        _campaign = camp; // weak ref
        _combatCharacters = [[NSMutableArray alloc] initWithCapacity:32];
        _initiativeIndex = -1;
        _entities = [[NSMutableArray alloc] initWithCapacity:32];
        _aftermath = [[NSMutableArray alloc] initWithCapacity:32];
        
        [self setInitiativeIndex:-1];
        [self reconcileCombatCharacters:target];
    }
    return self;
}

- initWithCoder:(NSCoder*)coder
{
    if ((self = [super init])) {
        _name = [[coder decodeObjectForKey:@"name"] retain];
        _comments = [[coder decodeObjectForKey:@"comments"] retain];
        _campaign = [coder decodeObjectForKey:@"campaign"]; // weak ref
        _combatCharacters = [[coder decodeObjectForKey:@"combatCharacters"] retain];
        _initiativeIndex = [coder decodeIntForKey:@"initiativeIndex"];
        _entities = [[coder decodeObjectForKey:@"entities"] retain];
        _aftermath = [[coder decodeObjectForKey:@"aftermath"] retain];
        
        [self setInitiativeIndex:_initiativeIndex];
    }
    return self;
}

- (void) encodeWithCoder:(NSCoder*)coder
{
    [coder encodeObject:_name forKey:@"name"];
    [coder encodeObject:_comments forKey:@"comments"];
    [coder encodeObject:_campaign forKey:@"campaign"];
    [coder encodeObject:_combatCharacters forKey:@"combatCharacters"];
    [coder encodeInt:_initiativeIndex forKey:@"initiativeIndex"];
    [coder encodeObject:_entities forKey:@"entities"];
    [coder encodeObject:_aftermath forKey:@"aftermath"];
}

- (void) dealloc
{
    [_aftermath release];
    [_entities release];
    [_combatCharacters release];
    [_name release];
    [_comments release];
    [super dealloc];
}

- description
{
    return [NSString stringWithFormat:@"Combat %p", self];
}

- (NSMutableArray*) entities
{
    return _entities;
}

- (int) initiativeIndex
{
    return _initiativeIndex;
}

- (Entity *) currentEntity
{
    return _currentEntity;
}

- (NSMutableArray*) targetedBy
{
    return _targetedBy;
}

- (Campaign*) campaign
{
    return _campaign;
}
    
- (NSMutableArray*) combatCharacters
{
    return _combatCharacters;
}

- (NSMutableArray*) aftermath
{
    return _aftermath;
}

- (NSString*) fieldAsString:(NSString*)field
{
    if ([field isEqualToString:kNAME])
        return _name;
    if ([field isEqualToString:kCOMMENTS])
        return _comments;
    return @"";
}

- (void) setFieldNamed:(NSString*)field to:(NSString*)value
{
    if ([field isEqualToString:@"Name"]) {
        [_name release];
        _name = [value retain];
    }
    else if ([field isEqualToString:@"Comments"]) {
        [_comments release];
        _comments = [value retain];
    }
        
}

- notifyObject
{
    return _campaign;
}

/* This method is invoked when our list of entities is changed
by an Action.  It gives us a chance to react. */
- (void) entitiesChanged:object
{
}

/* This method is invoked when the list of characters in the
campaign changes.  We then go through and adjust our combatCharacters
array. */
- (void) reconcileCombatCharacters:target
{
    int i;
    NSEnumerator *newchars=nil;
    NSMutableArray *chars=nil;
    Entity *newchar=nil;
    
    // get ourselves a local copy of the current characters
    // array; we'll be changing it
    chars = [[_campaign characters] copy];
    
    // go through each of our combat characters (wrappers around
    // the original set of characters that hold our combat-local data)
    // and check that they are still wrapping characters that exist.
    // If the char that they wrap no longer exists, purge them from the
    // list.
    for (i = [_combatCharacters count]-1; i >= 0; i--) {
        Entity *combatchar = [_combatCharacters objectAtIndex:i];
        int index = [chars indexOfObject:combatchar];
        if (index == NSNotFound) {
            [Action removeObject:combatchar from:_combatCharacters target:target];
        }
        else {
            // otherwise remove that character from the list of
            // campaign characters, later we'll create wrappers for
            // all that remain
            [chars removeObjectAtIndex:index];
        }
    }
    
    // create wrappers for all chars that are not removed yet
    newchars = [chars objectEnumerator];
    while ((newchar = [newchars nextObject])) {
        Entity *wrapper = [[[Entity alloc] initWithBase:newchar
                                           notifyObject:self] autorelease];
        [Action addObject:wrapper to:_combatCharacters atIndex:-1 target:target];
    }
}

- (void) setInitiativeIndex:(int)newval
{
    _initiativeIndex = newval;
    
    if (newval >= 0) {
        _currentEntity = [_entities objectAtIndex:newval];
        [_targetedBy release];
        _targetedBy = [[self whoTargets:_currentEntity] retain];
    }
    else {
        _currentEntity = nil;
        _targetedBy = nil;
    }
}

- (NSMutableArray*) whoTargets:(Entity*)target
{
    NSMutableArray *result = [[[NSMutableArray alloc] initWithCapacity:32] autorelease];
    
    NSEnumerator *allents = [_entities objectEnumerator];
    Entity *ent;
    while ((ent = [allents nextObject])) {
        if ([[ent targets] containsObject:target]) {
            [result addObject:ent];
        }
    }
    
    return result;
}

@end
