/*
    File:       FileInfo.m

    Contains:   Implementation for FileInfo, an object that gathers directory
                information from the user's filesystem

    Written by: Andy Wildenberg

    Created:    9 July 1997

    Copyright:  (c)1997 by Apple Computer, Inc., all rights reserved.

    Change History:
       version 1.0: first public version

    You may incorporate this sample code into your applications without
    restriction, though the sample code has been provided "AS IS" and the
    responsibility for its operation is 100% yours.  However, what you are
    not permitted to do is to redistribute the source as "DTS Sample Code"
    after having made changes. If you're going to re-distribute the source,
    we require that you make it clear in the source that the code was
    descended from Apple Sample Code, but that you've made changes.
*/


#import "FileInfo.h"

@implementation FileInfo

-(id) initWithPath:(NSString*) path
{
    NSFileManager* fileManager;
    NSDictionary* fileInformation;

    // this takes the current path and gets all the relevant information from the file system.
    self = [super init]; // must init myself properly first

    fileManager = [NSFileManager defaultManager];

    // first get the information about me
    fileInformation = [fileManager fileAttributesAtPath: path traverseLink:NO];

    // set the fullPathName to be the complete specification of where this file is
    fullPathName = [path copy];  // keep it around!
    filetype = [[fileInformation objectForKey: NSFileType] copy]; // copy all these, since we don't want them to change
    lastModified= [[fileInformation objectForKey: NSFileModificationDate] copy];

    // setup my subfolders appropriately
    containedFiles = nil;

    // note that we don't find anything out about the subfiles until we're queried about it

    // fix our filename to be just the tail end of the fullPathName
    filename = [[fullPathName lastPathComponent] copy];
    return self;
}


/* findContainedFiles does the hard work in the FileInfo class.  If self is a directory,  it gets a list of all the files contained in that directory, creates a FileInfo for  each of them and keeps an array with those FileInfo objects.  It is called internally,  and is called lazily -- if information about the children was gathered immediately, this would cause huge startup times since the entire file tree would have to be travesed to gather the appropriate information.
*/
- (void)findContainedFiles
{
    NSFileManager	*fileManager = [NSFileManager defaultManager];
    NSEnumerator	*enumerator;
    NSString		*currentFile;
    FileInfo		*fileInfo;
    NSArray		*filenames;
    NSMutableArray	*tempArray; // to build it up

    // get a list of all files contained in me
    filenames = [fileManager directoryContentsAtPath:fullPathName];

    // create the arrays to cache the data
    tempArray = [[NSMutableArray arrayWithCapacity: [filenames count]] retain];

    // okay, now iterate through the file list, adding info as we get to it
    enumerator = [filenames objectEnumerator];

    while ((currentFile = [enumerator nextObject]))
    {
        fileInfo = [[[self class] alloc] initWithPath: [fullPathName stringByAppendingPathComponent: currentFile]];
        if ( fileInfo )
            [tempArray addObject: fileInfo];
    }

    [self setContainedFiles:tempArray];
}

- (void)setContainedFiles:(NSArray *)value;
{
    [containedFiles autorelease];
    containedFiles = [[value sortedArrayUsingSelector:@selector(compare:)] retain];
}

/* containedFiles returns the NSArray of files contained in self.  If self is a  normal file, the answer is nil.  If self is a directory, the answer may be a 0 length array.  If self has never checked for the existence of children, it calls findContainedFiles to create the FileInfo objects for all its children.
*/
-(NSArray *) containedFiles;
{
    if (filetype == NSFileTypeDirectory)
    {
        if (containedFiles == nil)
        {
            //cache them up
            [self findContainedFiles];
        }
        return containedFiles;
    }
    else
        return nil;
}

// accessor functions for the FileInfo.
-(NSString*) filename
{
    return filename;
}

-(NSString*) fullPathName
{
    return fullPathName;
}

-(NSString*) filetype
{
    return filetype;
}

-(NSString*) lastModified
{
    return lastModified;
}

// cleanup functions
- (void)dealloc
{
    // this should never be called directly, but the system will call it when the
    // last copy of a particular object is released.  At this point it is necessary
    // to free all the objects that have been copied or retained by this object
    // NOTE: it is not necessary to check that the objects have already been allocated --
    // if they haven't they will be nil, and sending release to nil is guaranteed not
    // to cause an error or do anything stupid.  (actually sending nil to any object has
    // the same guarantee).
    [filename release];
    [filetype release];
    [lastModified release];
    [fullPathName release];
    [containedFiles release]; 
}

- (NSComparisonResult)compare:(FileInfo *)obj
{
    NSComparisonResult result = NSOrderedDescending;
    if ( obj )
    {
        result = [[self filetype] compare:[obj filetype]];
        if ( result == NSOrderedSame )
            result = [[self filename] compare:[obj filename]];
    }

    return result;
}

@end
