#pragma .h #import <Foundation/NSString.h>
#pragma .h #import <IconKit/iconkit.h>

#import <Foundation/NSDictionary.h>
#import <Foundation/NSPathUtilities.h>
#import <Foundation/NSProcessInfo.h>

#import <AppKit/NSWorkspace.h>

#import "File.h"
#import "FileList.h"

#pragma .h typedef struct _FileFlags {
#pragma .h 	unsigned int	imageLoaded:1;
#pragma .h 	unsigned int	acceptingDragImageLoaded:1;
#pragma .h 	unsigned int	parentLoaded:1;
#pragma .h 	unsigned int	childrenLoaded:1;
#pragma .h } FileFlags;

@implementation File: IKFolder
{
    NSString 	*path;
    FileFlags	fileFlags;
}

static NSImage				*draggedImage = nil;
static NSMutableDictionary	*fileMap = nil;

+ (void)initialize
{
    if (self == [File  class]) {
        fileMap = [[NSMutableDictionary  alloc]  init];
    }
    return;
}

+ multipleSelectionClass
{
	return [FileList class];
}

+ (NSArray *) pasteTypes
{
    static NSMutableArray *pasteTypes = nil;
    if(pasteTypes == nil) {
        pasteTypes = [[NSMutableArray array] retain];
        [pasteTypes addObject:NSFilenamesPboardType];
        [pasteTypes addObject:IKidPboardType()];
    }
    return pasteTypes;
}

+ fileForPath: (NSString *) thePath
{
    id file = [fileMap objectForKey: thePath];

    if (file == nil) {
        file = [[File alloc] initPath: thePath];
        [fileMap  setObject:file forKey:thePath];
    } else {
        [file retain];
    }
    return file;
}

- initPath: (NSString *) thePath
{
    NSString *title = [thePath lastPathComponent];
    if (title == nil)
        return nil;
    else
        if ([title isEqual:@""] || [title isEqual:@"/"]) {
            title = [[NSProcessInfo processInfo] hostName];
        }
    if ((self = [super init:title]) != nil) {
        NSDictionary *dict = [[NSFileManager defaultManager] fileAttributesAtPath:thePath traverseLink:NO];
        path = [thePath retain];
        flags.dragAccepting = [[dict fileType] isEqual:NSFileTypeDirectory];
        flags.leaf = !flags.dragAccepting;
        flags.hidden = NO;
        fileFlags.imageLoaded = NO;
        fileFlags.acceptingDragImageLoaded = NO;
        fileFlags.parentLoaded = NO;
        fileFlags.childrenLoaded = !flags.dragAccepting;
    }
    return self;
}

- copyWithZone: (NSZone *) zone;
{
    File *copy = [super copyWithZone: zone];

    copy->path = [path copyWithZone:zone];
    copy->fileFlags = fileFlags;
    return copy;
}

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

- image
{
    if (!fileFlags.imageLoaded)
        image = draggedImage
            ? draggedImage
            : [[[NSWorkspace sharedWorkspace] iconForFile:path] retain];
    fileFlags.imageLoaded = 1;
    return image;
}

- (NSString *) path
{
	return path;
}

- parents
{
    NSString *directory;

    if (!fileFlags.parentLoaded) {
        fileFlags.parentLoaded = 1;
        directory = [path stringByDeletingLastPathComponent];
        if([directory isEqual:@""]) {
            [[File fileForPath:@"/"] addChild: self];
        } else {
            [[File fileForPath:directory] addChild: self];
        }
    }	
    return parents;
}

- (void)addParent: parent
{
    fileFlags.parentLoaded = 1;
    [super addParent: parent];
}

- (void)removeChild:child withAnnouncement:(BOOL)yesNo
{
    NSEnumerator *enumerator = [fileMap keyEnumerator];
    NSString     *key, *p = [child path];
    fileFlags.childrenLoaded = 0;
    while(key = [enumerator nextObject]) {
        if([key hasPrefix:p]) {
            [fileMap removeObjectForKey:key];
        }
    }
    [fileMap removeObjectForKey:p];
    [super removeChild:child withAnnouncement:yesNo];
}

- children
{
    int i, count;

    if (!fileFlags.childrenLoaded) {
        NSArray *files = [[NSFileManager defaultManager] directoryContentsAtPath:path];
        fileFlags.childrenLoaded = 1;
        [users setSendAnnouncements: NO];
        for(i = 0, count = [files count]; i < count; i++) {
            NSString *s = [files objectAtIndex:i];
            [self  addChild: [File fileForPath:[path stringByAppendingPathComponent:s]]];
        }
        [users  setSendAnnouncements: YES];
    }
    return children;
}

- (void)copyToPasteboard: (NSPasteboard *) pboard
{
    [super  copyToPasteboard: pboard];
    [pboard addTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:nil];
    [pboard setPropertyList:[NSArray arrayWithObject:path] forType:NSFilenamesPboardType];
}

+ readFromPasteboard: (NSPasteboard *) pboard
{
    id file = nil;
    if ((file = [super readFromPasteboard: pboard]) == nil && [pboard availableTypeFromArray:[NSArray arrayWithObject:NSFilenamesPboardType]] != NULL) {
        id a = [pboard propertyListForType:NSFilenamesPboardType];
        if([a isKindOfClass:[NSString class]]) {
            file = [File fileForPath:a];
        } else if([a isKindOfClass:[NSArray class]]) {
            if([a count] > 1) {
                file = [FileList readFromPasteboard:pboard];
            } else {
                file = [File fileForPath:[a objectAtIndex:0]];
            }
       }
    }
    return file;
}

/* shelf listener methods */

+ (void)shelf:sender dragWillEnter: (id <NSDraggingInfo>) source
{
    draggedImage = [source draggedImage];
}

+ (void)shelf:sender dragWillExit: (id <NSDraggingInfo>) source
{
    draggedImage = nil;
}

+ (void)shelf:sender dragWillComplete: (id <NSDraggingInfo>) source
{
    draggedImage = nil;
}


@end
