//
//  MPT_SourceLoader.m
//  AUCoderDemo
//
//  Created by Andrew Salamon on 6/6/08.
//  Copyright 2008 Machine Perception Laboratory, University of California San Diego.. All rights reserved.
//

#import <QTKit/QTMovie.h>

#import "MPT_SourceLoader.h"

#import "MPT_ResolveAlias.h"
#import "MPT_Pair.h"

@interface MPT_SourceLoader(PrivateMethods)
- (void)processMovieAtPath:(NSString *)path;
- (void)processFolder:(NSString *)folderPath;
- (void)threadedProcessSources:(NSArray *)sources;
@end

@implementation MPT_SourceLoader
- (id)initWithDelegate:(id)_delegate imageTypes:(NSArray *)itypes movieTypes:(NSArray *)mtypes
{
	if( self= [super init] )
	{
		delegate = _delegate;
		interrupt = NO;
		fileManager = [[NSFileManager defaultManager] retain];
		imageTypes = [itypes retain];
		movieTypes = [mtypes retain];
	}
	return self;
}

- (void)dealloc
{
	[fileManager release];
	[imageTypes release];
	[movieTypes release];
	[super dealloc];
}

- (void)interrupt
{
	interrupt = YES;
}

- (void)checkPool
{
	++poolCount;
	if( poolCount > 20 )
	{
		[pool release];
		pool = [[NSAutoreleasePool alloc] init];
		poolCount = 0;
	}
}

- (void)imageChanged:(id)change
{
	// This is safe so long as imageChanged doesn't update any UI elements. Right now it just calls through to the scheduler, which starts a new thread.
	[delegate imageChanged:change];
//	[delegate performSelectorOnMainThread:@selector(imageChanged:) withObject:change waitUntilDone:YES];
}

- (void)processSources:(NSArray *)sources
{
	[NSThread detachNewThreadSelector:@selector(threadedProcessSources:) toTarget:self withObject:sources];
}

- (void)threadedProcessSources:(NSArray *)sources
{
	[sources retain];
	pool = [[NSAutoreleasePool alloc] init];
	poolCount = 0;
	
	NSEnumerator *sourceEnum = [[sources objectEnumerator] retain];
	NSString *sourcePath;

	interrupt = NO;
	
	while( !interrupt && (sourcePath = [sourceEnum nextObject]) )
	{
		sourcePath = [[[sourcePath stringByStandardizingPath] stringByResolvingSymlinksInPath] stringByResolvingAliases];
		NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:sourcePath traverseLink:YES];
		
		if( [[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeDirectory] )
		{
			[self processFolder:sourcePath];
		}
		else if( [[sourcePath pathExtension] hasPrefix:@"rimage"] )
		{
			[self imageChanged:sourcePath];
		}
		else if( [imageTypes containsObject:[sourcePath pathExtension]] )
		{
			NSImage *image = [[NSImage alloc] initWithContentsOfFile:sourcePath];
			if( image )
			{
				[self imageChanged:[MPT_Pair pairWith:image and:sourcePath]];
				[image release];
			}
		}
		else if( [movieTypes containsObject:[sourcePath pathExtension]] )
		{
//			[self performSelectorOnMainThread:@selector(processMovieAtPath:) withObject:sourcePath waitUntilDone:YES];
			[self processMovieAtPath:sourcePath];		
		}
		else
		{
			NSLog( @"Skipping file of unknown type: %@", sourcePath );
		}

		[self checkPool];
	}

	
	interrupt = YES;
	[sources release];
	[sourceEnum release];
	[pool release];
	
	[delegate performSelectorOnMainThread:@selector(sourceProcessingFinished) withObject:nil waitUntilDone:NO];
}

- (void)processFolder:(NSString *)folderPath
{
	[folderPath retain];
	
	NSArray *imagesInFolder = [[[NSFileManager defaultManager] directoryContentsAtPath:folderPath] retain];
	NSEnumerator *imageFolderEnum = [[imagesInFolder objectEnumerator] retain];
	
	NSString *imageName;
	
	while( !interrupt && (imageName = [imageFolderEnum nextObject]) )
	{
		NSString *imagePath = [[[[folderPath stringByAppendingPathComponent:imageName] stringByStandardizingPath] stringByResolvingSymlinksInPath] stringByResolvingAliases];
		NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:imagePath traverseLink:YES];
		
		if( [[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeRegular]
			|| [[fileAttributes objectForKey:NSFileType] isEqualToString:NSFileTypeSymbolicLink] )
		{
			NSImage *image = [[NSImage alloc] initWithContentsOfFile:imagePath];
			if( image )
			{
				[self imageChanged:[MPT_Pair pairWith:image and:imagePath]];
				[image release];
			}
			else
			{
				if( [[imagePath pathExtension] isEqualToString:@"rimage"] )
				{
					[self imageChanged:imagePath];
				}
			}			
		}
		
		[self checkPool];
	}

	[folderPath release];
	[imagesInFolder release];
	[imageFolderEnum release];
}

- (void)processMovieAtPath:(NSString *)path
{
	NSError *error = nil;
	QTMovie *movie = [QTMovie movieWithFile:path error:&error];
	
	if( error )
	{
		NSAlert *alert = [NSAlert alertWithError:error];
		[alert runModal];
		movie = nil;
		return;
	}
	else
	{
		[path retain];
		[movie retain];
	}
	
	[movie gotoEnd];
	QTTime endTime = [movie currentTime];
	[movie gotoBeginning];
	unsigned int movieFrame = 1;
	QTTime currentTime = [movie currentTime];

	while( !interrupt && !(NSOrderedDescending != QTTimeCompare( endTime, currentTime )) )
	{
		[self imageChanged:[MPT_Pair pairWith:[movie currentFrameImage] and:[NSString stringWithFormat:@"%@:%d", path, movieFrame]]];
		[movie stepForward];
		++movieFrame;
		currentTime = [movie currentTime];
		
		[self checkPool];
	}

	[movie release];
	[path release];
}
@end
