#import "CampaignController.h"
#import "CampaignDocument.h"
#import "Entity.h"
#import "Actions.h"
#import "NamePrompter.h"
#import "FieldTableManager.h"
#import "Config.h"
#import "CombatController.h"
#import "dice.h"

// the indentifiers of the various "tab view items"
#define CHARACTERSTV 1
#define COMBATSTV     2

@implementation CampaignController

- init
{
    if ((self = [super initWithWindowNibName:@"Campaign"])) {
        [self setShouldCloseDocument:YES];
    }
    return self;
}

- (void) dealloc
{
    [_charactersManager release];
    [_combatsManager release];
    [super dealloc];
}

- (Campaign*) campaign
{
    return [[self document] campaign];
}

- (void) awakeFromNib
{
    //[_characters setAction:@selector (clearSkillRolls)];
    /* Create managers for each table.  Note that the "current character effects" manager's array
    will change as initiative changes, but that's no big deal */
    _charactersManager = [[FieldTableManager alloc] initWithColumns:kCAMPAIGNCHARSET
                                                               data:[[self campaign] characters]
                                                        NSTableView:_characters
                                                           readOnly:NO
                                                             notify:[self campaign]
                                                           delegate:self];
    _combatsManager = [[FieldTableManager alloc] initWithColumns:kCAMPAIGNCOMBSET 
                                                            data:[[self campaign] combats]
                                                     NSTableView:_combats
                                                        readOnly:NO
                                                          notify:[self campaign]
                                                        delegate:self];
}

- (IBAction)addBattle:(id)sender
{
    [NamePrompter promptForName:self selector:@selector(addBattleWithName:) window:[self window]];
}

- (void) addBattleWithName:(NSString*)name
{
    Combat *combat = [[[Combat alloc] initWithCampaign:[self campaign] name:name target:self] autorelease];
    [Action addObject:combat
                   to:[[self campaign] combats]
              atIndex:-1
               target:self];
}

- (void) resumeBattle:sender
{
    NSEnumerator *selrows = [_combats selectedRowEnumerator];
    NSNumber *row;
    
    while ( (row = [selrows nextObject]) ) {
        Combat *comb = [[[self campaign] combats] objectAtIndex:[row intValue]];
        
        /* check if it already has a window started */
        NSEnumerator *conts = [[[self document] 
            windowControllers] 
            objectEnumerator];
        id cont;
        while ((cont = [conts nextObject])) {
            if ([cont respondsToSelector:@selector(combat)]) {
                Combat *cdata = [cont combat];
                if (cdata == comb) {
                    [[cont window] makeKeyAndOrderFront:self];
                    return;
                }
            }
        }
        
        cont = [[[CombatController alloc] initWithCombat:comb] autorelease];    
        [[self document] addWindowController:cont];
        [cont showWindow:self];
    }
}

/* When the user clicks on "add NPC" or "add PC", open up a modal prompter asking for the name.
Only if they type in a name and click "add" will we go to "add[N]PCWithName", both of which
call the helper addCharacterWithName */

- (void) addCharacterWithName:(NSString*)name type:(NSString*)type
{
    Entity *chr = [[[Entity alloc] initWithBase:nil
                                   notifyObject:[self campaign]] autorelease];
    
    [chr setFieldNamed:kNAME to:name];
    [chr setFieldNamed:kTYPE to:type];
    
    [Action addObject:chr
                   to:[[self campaign] characters]
              atIndex:-1
               target:self];
}

- (IBAction)addNPC:(id)sender
{
    [NamePrompter promptForName:self selector:@selector(addNPCWithName:) window:[self window]];
}

- (void) addNPCWithName:(NSString*)name
{
    [self addCharacterWithName:name type:kNPC];
}

- (IBAction)addPC:(id)sender
{
    [NamePrompter promptForName:self selector:@selector(addPCWithName:) window:[self window]];
}

- (void) addPCWithName:(NSString*)name
{
    [self addCharacterWithName:name type:kPC];
}

- (IBAction) rollSkills:(id)sender
{
    [_skillRolls release];
    _skillRolls = [[NSMutableDictionary alloc] initWithCapacity:32];
    [_characters reloadData];
}

- (IBAction) clearSkillRolls:(id)sender
{
    [_skillRolls release];
    _skillRolls = nil;
    [_characters reloadData];
}

- (NSAttributedString*)fieldTableManager:(FieldTableManager*)manager
                        attributizeValue:(NSString*)value
                                  forRow:(int)row
                                   field:(NSString*)field
                                    font:(NSFont*)origfont
                                  object:(id)entity
{
    // we only use this method to add rolled versions of skills...
    if (manager != _charactersManager || !IsBonus (EntitySchema(), field) || !_skillRolls)
        return [[[NSAttributedString alloc] initWithString:value] autorelease];

    // get dictionary of skill rolls for this char, if any.
    // note that rather than use the entity as a key directly
    // we use its pointer encoded in a nsnumber: these rolls won't
    // be on screen for long, and NSDictionaries do funny things
    // with keys (like send them copy messages)
    NSNumber *entkey = [NSNumber numberWithLong:(long)entity];
    NSMutableDictionary *entrolls = [_skillRolls objectForKey:entkey];
    if (!entrolls) {
        entrolls = [NSMutableDictionary dictionaryWithCapacity:4];
        [_skillRolls setObject:entrolls forKey:entkey];
    }
    
    // get resulting string from dic, if any
    NSAttributedString *result = [entrolls objectForKey:field];
    if (!result) {
        int bonus = [value rolledValue];
        int roll = RollDie (20) + bonus;
        
        NSMutableAttributedString *mutatt = 
            [[[NSMutableAttributedString alloc] init] autorelease];
        
        [mutatt appendAttributedString:
            [[[NSAttributedString alloc] initWithString:value] autorelease]];
        [mutatt appendAttributedString:
            [[[NSAttributedString alloc] 
            initWithString:[NSString stringWithFormat:@" (%d)", roll] 
                attributes:[NSDictionary 
                dictionaryWithObjectsAndKeys:[NSColor redColor], NSForegroundColorAttributeName, nil]]
                autorelease]];
        result = mutatt;
        [entrolls setObject:result forKey:field];
    }
    
    return result;
}

- (IBAction)delete:(id)sender
{
    NSTableView *table=nil;
    NSMutableArray *dataarray=nil;
    
    switch ([[[_tabView selectedTabViewItem] identifier] intValue])
    {
        case CHARACTERSTV: 
            table = _characters;
            dataarray = [[self campaign] characters];
            break;
        
        case COMBATSTV:
            table = _combats;
            dataarray = [[self campaign] combats];
            break;
    }
    
    NSEnumerator *selected = [table selectedRowEnumerator];
    NSMutableArray *tokill = [NSMutableArray arrayWithCapacity:32];
    NSNumber *row;
    while ( (row = [selected nextObject]) ) {
        id obj = [dataarray objectAtIndex:[row intValue]];
        [tokill addObject:obj];
    }        
    
    selected = [tokill objectEnumerator];
    id deadman;
    while ((deadman = [selected nextObject])) {
        [Action removeObject:deadman
                        from:dataarray
                      target:self];
    }
}

/* Undo handling */

- (void) undoAction:(Action*)a
{
    [a commit];
}

- (NSUndoManager*) undoManager
{
    return [[self window] undoManager];
}

@end
