/*
 * Copyright (c) 2010 David McIntosh <dmcintosh@df12.net>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#import "GanttModel.h"

@implementation GanttModel

-(id)init
{
    self = [super init];
    if (self)
    {
        tasks = [[NSMutableArray alloc] init];
        tasksDict = [[NSMutableDictionary alloc] init];
    }
    return self;
}

- (void) encodeWithCoder: (NSCoder *) encoder 
{
    [encoder encodeObject:tasks forKey:@"tasks"];
}

- (id) initWithCoder: (NSCoder *) decoder 
{
    self = [self init];
    ASSIGN(tasks, [decoder decodeObjectForKey:@"tasks"]);
    NSEnumerator *e = [tasks objectEnumerator];
    GanttTask *task;
    NSInteger tag;
    while (( task = [e nextObject] ))
    {
        tag = [task tag];
        [tasksDict setObject:task
                      forKey:[NSNumber numberWithInt:tag]];
    }
    return self;
}

-(GanttTask *)taskAtIndex:(NSUInteger)index
{
    if (index >= [tasks count])
    {
        UKLog(@"Index %d is out of bounds for task list", index);
        // NSLog(@"%@",[NSThread callStackSymbols]);
        return nil;
    }
    return [tasks objectAtIndex:index];
}

-(GanttTask *)taskForTag:(NSInteger)tag
{
    return [tasksDict objectForKey:
        [NSNumber numberWithInt:tag]];
}

-(void)removeTaskWithTag:(NSInteger)tag
{
    NSNumber *tagNumber = [NSNumber numberWithInt:tag];
    GanttTask *task = [tasksDict objectForKey:tagNumber];
    [tasksDict removeObjectForKey:tagNumber];
    GanttTask *parent = [task parent];
    if (nil == parent)
        [tasks removeObjectIdenticalTo:task];
    else
        [parent removeChild:task];
}

-(void)addTask:(GanttTask *)aTask
{
    NSInteger tag = [aTask tag];
    [tasks addObject:aTask];
    [tasksDict setObject:aTask
                  forKey:[NSNumber numberWithInt:tag]];
}

-(void)addChild:(GanttTask *)task toTaskWithTag:(NSInteger)tag
{
    GanttTask *parent = [self taskForTag:tag];
    [parent addChild:task];
    [tasksDict setObject:task
        forKey:[NSNumber numberWithInt:[task tag]]];
}

-(NSUInteger)count
{
    return [tasks count];
}

-(NSEnumerator *)rootTaskEnumerator
{
    return [tasks objectEnumerator];
}

-(NSDate *)earliestStartDate
{
    NSDate *startDate;
    NSDate *earliest = nil;
    NSEnumerator *e = [self rootTaskEnumerator];
    GanttTask *task;
    while ((task = [e nextObject]))
    {
        startDate = [task startDate];
        earliest = earliest?[earliest min:startDate]:startDate;
    }
    return earliest;
}

-(NSDate *)latestEndDate
{
    NSDate *endDate;
    NSDate *latest = nil;
    NSEnumerator *e = [self rootTaskEnumerator];
    GanttTask *task;
    while ((task = [e nextObject]))
    {
        endDate = [task endDate];
        latest = latest?[latest max:endDate]:endDate;
    }
    return latest;
}

-(void)dealloc
{
    [super dealloc];
    DESTROY(tasks);
    DESTROY(tasksDict);
}

@end
