//
//  FileSource.m
//  FileSource
//
//  Created by Vincent Spader on 3/1/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "FileSource.h"


@implementation FileSource

+ (void)initialize
{
    fex_init();
}

- (id)init
{
    self = [super init];
    if ( self ) {
        fex = NULL;
        _fd = NULL;
    }
    return self;
}

- (BOOL)open:(NSURL *)url
{
	[self setURL:url];
    
    NSString * path = [url path];
    
    fex_type_t type;
    fex_err_t error = fex_identify_file( &type, [path UTF8String] );
    
    if ( !error && type && strcmp( fex_type_name( type ), "file" ) ) {
        error = fex_open_type( &fex, [path UTF8String], type );
        if ( !error ) {
            while ( !fex_done( fex ) ) {
                NSString * name = [[NSString stringWithUTF8String:fex_name( fex )] lowercaseString];
                if ( [name hasSuffix:@".diz"] || [name hasSuffix:@".txt"] || [name hasSuffix:@".nfo"] ) {
                    error = fex_next( fex );
                    if ( error )
                        return NO;
                    continue;
                }
                break;
            }
            if ( fex_done( fex ) )
                return NO;

            error = fex_data( fex, &data );
            if ( error )
                return NO;
            
            size = fex_size( fex );
            offset = 0;
            
            return YES;
        }
        else return NO;
    }
	
	_fd = fopen([[url path] UTF8String], "r");
	
	return (_fd != NULL);
}

- (BOOL)seekable
{
	return YES;
}

- (BOOL)seek:(long)position whence:(int)whence
{
    if ( fex ) {
        switch ( whence ) {
            case SEEK_CUR:
                position += offset;
                break;
                
            case SEEK_END:
                position += size;
                break;
        }

        offset = position;
        
        return (position >= 0) && (position < size);
    }
    
	return (fseek(_fd, position, whence) == 0);
}

- (long)tell
{
    if ( fex ) return offset;
	else return ftell(_fd);
}

- (long)read:(void *)buffer amount:(long)amount
{
    if ( fex ) {
        if ( amount + offset > size )
            amount = size - offset;
        memcpy( buffer, (const char *)data + offset, amount );
        offset += amount;
        return amount;
    }
    else {
        return fread(buffer, 1, amount, _fd);
    }
}

- (void)close
{
	if (_fd) 
	{
		fclose(_fd);
		_fd = NULL;
	}

    if ( fex ) {
        fex_close( fex );
        fex = NULL;
    }
}

- (NSURL *)url
{
	return _url;
}

- (NSString *)mimeType
{
	return nil;
}

- (void)setURL:(NSURL *)url
{
	[url retain];
	[_url release];
	_url = url;
}


+ (NSArray *)schemes
{
	return [NSArray arrayWithObject:@"file"];
}

- (void)dealloc {
	[self close];
	[self setURL:nil];
	
	[super dealloc];
}

@end