//
//  Entity.m
//  longspear
//
//  Created by Niko Matsakis on Thu Jun 10 2004.
//  Copyright (c) 2004 __MyCompanyName__. All rights reserved.
//

#import "Entity.h"
#import "Config.h"
#import "EntitySchema.h"
#import "Actions.h"

@implementation Entity

- initWithBase:(Entity*)base notifyObject:notify
{
    if ( (self=[super init]) ) {
        if (base) _base = [base retain];
        _fields = [[NSMutableDictionary alloc] initWithCapacity:32];
        _notifyObject = notify; // weak reference
        _targets = [[NSArray arrayWithObjects:nil] retain];
    }
    return self;
}

- initWithCoder:coder
{
    if ((self = [super init])) {
        _base = [[coder decodeObjectForKey:@"base"] retain];
        _fields = [[coder decodeObjectForKey:@"fields"] retain];
        _targets = [[coder decodeObjectForKey:@"targets"] retain];
        _notifyObject = [coder decodeObjectForKey:@"notify"];
    }
    return self;
}

- copyWithZone:(NSZone*)zone
{
    Entity* copy = [[[Entity allocWithZone:zone] init] autorelease];
    if (_base) copy->_base = [_base retain];
    copy->_fields = [[_fields copyWithZone:zone] retain];
    copy->_targets = [[_fields copyWithZone:zone] retain];
    copy->_notifyObject = _notifyObject;
    return copy;
}

- (void) encodeWithCoder:(NSCoder*)coder
{
    [coder encodeObject:_base forKey:@"base"];
    [coder encodeObject:_fields forKey:@"fields"];
    [coder encodeObject:_targets forKey:@"targets"];
    [coder encodeObject:_notifyObject forKey:@"notify"];
}

- (void) dealloc
{
    [_base release];
    [_fields release];
    [_targets release];
    [super dealloc];
}

- (void) setTargetList:(NSArray*)targets actionTarget:actiontarget
{
    [_targets release];
    _targets = [targets retain];
    
    NSString *myname = [self fieldAsString:kNAME];
    
    // adjust the affected by lists on our targets by adding "{name} ":
    NSEnumerator *nsenum = [targets objectEnumerator];
    id target;
    while ( (target=[nsenum nextObject]) ) {
        NSString *prevaffect = [target fieldAsString:kAFFECTEDBY];
        NSString *newaffect = [NSString stringWithFormat:@"%@ %@", myname, prevaffect];
        [Action setFieldNamed:kAFFECTEDBY
                           to:newaffect
                           on:target
                       target:actiontarget];
    }
}

- (void) removeTargetListActionTarget:actiontarget
{
    NSString *myname = [NSString stringWithFormat:@"%@ ", [self fieldAsString:kNAME]];
    
    // adjust the affected by lists on our targets to remove the "{name} " we added earlier:
    NSEnumerator *nsenum = [_targets objectEnumerator];
    id target;
    while ( (target=[nsenum nextObject]) ) {
        NSString *prevaffect = [target fieldAsString:kAFFECTEDBY];
        NSRange myrange = [prevaffect rangeOfString:myname];
        if (myrange.location != NSNotFound) {
            NSMutableString *copy = [[[NSMutableString alloc] initWithCapacity:[prevaffect length]] autorelease];
            [copy appendString:prevaffect];
            [copy deleteCharactersInRange:myrange];
            [Action setFieldNamed:kAFFECTEDBY
                               to:copy
                               on:target
                           target:actiontarget];
        }
    }
}

- description
{
    return [NSString stringWithFormat:@"Entity %@",
        [self fieldAsString:kNAME]];
}

- notifyObject
{
    return _notifyObject;
}

- (Entity*) base
{
    return _base;
}

- (NSArray*) fieldNames
{
    return [_fields allKeys];
}

- (NSDictionary*) fields
{
    return _fields;
}

- (void) setFieldsFrom:(NSDictionary*)dict interpret:(BOOL)interpret
{
    NSEnumerator *enumer = [dict keyEnumerator];
    NSMutableDictionary *schema = EntitySchema ();
    NSString *key;
    
    while ((key = [enumer nextObject])) {
        NSString *value = [dict objectForKey:key];
        
        // First allow the entity schema to process the
        // value.
        if (interpret)
            value = PrepareEnteredValue (schema, key, value);
        
        [self setFieldNamed:[key description]
                         to:[value description]];
    }
}

- (void) setFieldNamed:(NSString*)name to:(NSString*)value
{
    [_fields setObject:value forKey:name];
}

- (void) setFieldNamed:(NSString*)name toInt:(int)value
{
    [self setFieldNamed:name to:[NSString stringWithFormat:@"%d", value]];
}

- (NSString*) fieldAsString:(NSString*)name
{
    NSString *res = [_fields objectForKey:name];
    if (!res && _base) return [_base fieldAsString:name];
    if (!res) return @"";
    return res;
}

- (int) fieldAsInt:(NSString*)name
{
    NSString *res = [_fields objectForKey:name];
    if (!res && _base) return [_base fieldAsInt:name];
    if (!res) return 0;
    return [res intValue];
}

- (NSArray*) targets
{
    return _targets;
}

@end
