// Copyright 1997-1999 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "OWFileProcessor.h"

#import <Foundation/Foundation.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>

#import "OWAddress.h"
#import "OWFileDataStream.h"
#import "OWFileInfo.h"
#import "OWObjectStream.h"
#import "OWPipeline.h"
#import "OWSourceProcessor.h"
#import "OWTimeStamp.h"
#import "OWURL.h"

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OWF/Processors.subproj/Protocols.subproj/OWFileProcessor.m,v 1.6 1999/03/30 21:26:34 kc Exp $")

@interface OWFileProcessor (Private)
- (void)processDirectoryAtPath:(NSString *)filePath;
- (void)fetchDirectory:(OFDirectory *)directory;
- (void)fetchRegularFile:(NSString *)filePath;
- (BOOL)redirectToFTP;
@end

@implementation OWFileProcessor

static NSString *directoryIndexFilename;

+ (void)initialize;
{
    static BOOL initialized = NO;

    [super initialize];
    if (initialized)
	return;
    initialized = YES;

    directoryIndexFilename = nil;
}

+ (void)didLoad;
{
    [self registerProcessorClass:self fromContentType:[OWURL contentTypeForScheme:@"file"] toContentType:[OWSourceProcessor sourceContentType] cost:1.0];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(controllerDidInit:) name:OFControllerDidInitNotification object:nil];
}

+ (void)controllerDidInit:(NSNotification *)notification;
{
    [self readDefaults];
}

+ (void)readDefaults;
{
    OFUserDefaults *userDefaults;

    userDefaults = [OFUserDefaults sharedUserDefaults];
    directoryIndexFilename = [userDefaults stringForKey:@"OWDirectoryIndexFilename"];
}

- initWithPipeline:(OWPipeline *)aPipeline;
{
    if (![super initWithPipeline:aPipeline])
        return nil;

    fileAddress = [(OWAddress *)[pipeline lastContent] retain];

    return self;
}

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

- (void)process;
{
    NSString *filePath;
    OFFile *file;
    NSDate *lastChanged;

    filePath = [fileAddress localFilename];
    file = [OFUnixFile fileWithPath:filePath];

    NS_DURING {
	lastChanged = [file lastChanged];
    } NS_HANDLER {
        if ([self redirectToFTP])
	    return;
	[localException raise];
    } NS_ENDHANDLER;

    [OWTimeStamp cacheDate:lastChanged forAddress:[pipeline lastAddress]];

    if (![file isDirectory]) {
	[self fetchRegularFile:filePath];
	return;
    }

    if ([filePath hasSuffix:@"/"]) {
	[self fetchDirectory:[OFUnixDirectory directoryWithFile:file]];
	return;
    }

    [self processDirectoryAtPath:filePath];
}

@end

@implementation OWFileProcessor (Private)

- (void)processDirectoryAtPath:(NSString *)filePath;
{
#warning Document wrappers (including RTFD) are not supported at present

    // Redirect from file:/.../x to file:/.../x/
    [pipeline addSourceContent:[OWAddress addressWithFilename:[filePath stringByAppendingString:@"/"]]];
    [pipeline cacheContent];
    [pipeline startProcessingContent];
}

- (void)fetchDirectory:(OFDirectory *)directory;
{
    OWObjectStream *objectStream;
    NSArray *files;
    unsigned int fileIndex, fileCount;

    [self setStatusString:@"Reading directory"];

    if (directoryIndexFilename && [directory containsFileNamed:directoryIndexFilename]) {
	[self fetchRegularFile:[[directory path] stringByAppendingPathComponent:directoryIndexFilename]];
	return;
    }

    objectStream = [[OWObjectStream alloc] init];
    [objectStream setContentTypeString:@"ObjectStream/OWFileInfoList"];
    [pipeline addSourceContent:objectStream];
    [pipeline cacheContent];
    files = [directory sortedFiles];
    fileCount = [files count];
    for (fileIndex = 0; fileIndex < fileCount; fileIndex++) {
        OFFile *file;
        OWFileInfo *fileInfo;

        file = [files objectAtIndex:fileIndex];
        fileInfo = [[OWFileInfo alloc] initWithAddress:[OWAddress addressWithFilename:[file path]] size:[file size] isDirectory:[file isDirectory] isShortcut:[file isShortcut] lastChangeDate:[[file lastChanged] dateWithCalendarFormat:@"%d-%b-%Y %H:%M:%S %z" timeZone:nil]];
        [objectStream writeObject:fileInfo];
        [fileInfo release];
    }
    [objectStream dataEnd];
    [objectStream release];
    [pipeline startProcessingContent];
}

- (void)fetchRegularFile:(NSString *)filePath;
{
    OWDataStream *fileStream;

    [self setStatusString:@"Reading file"];
    fileStream = [[OWFileDataStream alloc] initWithContentsOfMappedFile:filePath];
    [fileStream setContentTypeAndEncodingFromFilename:filePath];
    [pipeline addSourceContent:fileStream];
    [fileStream release];
    [pipeline cacheContent];
    [self setStatusString:@"Finished reading"];
    [pipeline startProcessingContent];
}

- (BOOL)redirectToFTP;
{
    OWURL *url;
    NSString *netLocation;

    url = [fileAddress url];
    netLocation = [url netLocation];
    if (!netLocation || [netLocation length] == 0 ||
	[netLocation isEqualToString:@"localhost"])
	return NO;

    [pipeline addSourceContent:[OWAddress addressWithURL:[OWURL urlWithScheme:@"ftp" netLocation:netLocation path:[url path] params:[url params] query:[url query] fragment:[url fragment]]]];
    [pipeline startProcessingContent];
    return YES;
}

@end
