#import <Foundation/Foundation.h>

#define WATCH_PATH @"target path"
#define WATCH_FILE_ATTR @"target file atrributes"
#define WATCH_FILE_MODIFIED @"target file modified"

@interface Watcher : NSObject
{
	NSMutableDictionary	*targetPathes;
	NSFileManager		*manager;
	NSMutableDictionary	*fileAttributes;
}
- (id)initWithTargetPathes:(NSArray *)pathes;
- (void)checkModified;
@end

@implementation Watcher
- (id)initWithTargetPathes:(NSArray *)pathes;
{
	targetPathes	= [NSMutableDictionary dictionary];
	manager			= [NSFileManager defaultManager];
	fileAttributes	= [NSMutableDictionary dictionary];
	for (NSString *path in pathes)
	{
		[targetPathes setValue:path forKey:path];
		NSDictionary *status = [manager fileAttributesAtPath:path traverseLink:YES];
		if (status) [fileAttributes setValue:status forKey:path];
	}
	return self;
}
- (void)sendNotification:(NSString *)aPath withStatus:(id)aStatus
{
	NSString *message = [NSString stringWithFormat:@"'%@' is modified!", aPath];
	[[NSNotificationCenter defaultCenter] postNotificationName:WATCH_FILE_MODIFIED
														object:message
													  userInfo:aStatus];
	return;
}
- (void)checkModified
{
	for (NSString *path in targetPathes)
	{
		NSAutoreleasePool *pool	= [NSAutoreleasePool new];
		NSDictionary *_prev		= [fileAttributes objectForKey:path];
		NSDictionary *_current	= [manager fileAttributesAtPath:path traverseLink:YES];
		if (_prev || _current)
		{
			if (!_current)
			{
				[fileAttributes removeObjectForKey:path];
				[self sendNotification:path withStatus:nil];
			}
			else if (![_current isEqual:_prev])
			{
				[fileAttributes setObject:[_current copy] forKey:path];
				[self sendNotification:path withStatus:_current];
			}
		}
		[pool release];
	}
	return;
}
@end

@interface FileStatusLogger : NSObject
{
    NSNotificationCenter* center;
}
- (id)initWithNotificationCenter:(NSNotificationCenter *)aCenter;
- (void)log:(NSNotification *)notice;
@end

@implementation FileStatusLogger
- (id)initWithNotificationCenter:(NSNotificationCenter *)aCenter
{
	[super init];
	[aCenter addObserver:self selector:@selector(log:) name:WATCH_FILE_MODIFIED object:nil];
	return self;
}
- (id)init
{
	return [self initWithNotificationCenter:[NSNotificationCenter defaultCenter]];
}
- (void)log:(NSNotification *)notice;
{
	NSLog(@"%@", [notice object]);
	return;
}
@end

void usage(name)
{
	printf("Usage: %s <interval> <duration> <path1> [<path2>...]\n", name);
	exit(1);
}

int main(int argc, char *argv[])
{
	if (argc < 4) usage(argv[0]);
    
    NSAutoreleasePool *pool	= [NSAutoreleasePool new];
    NSMutableArray *pathes	= [NSMutableArray array];
    NSTimeInterval interval	= strtod(argv[1], NULL);
    NSTimeInterval duration	= strtod(argv[2], NULL);
	
	if (interval <= 0) usage(argv[0]);

    int i;
    for (i = 3; i < argc; i++)
    {
    	[pathes addObject:[NSString stringWithCString:argv[i]]];
    }

    Watcher *watcher			= [[Watcher alloc] initWithTargetPathes:pathes];
    FileStatusLogger *logger	= [FileStatusLogger new];
    NSTimer *timer				= [NSTimer scheduledTimerWithTimeInterval:interval
    															   target:watcher
    															 selector:@selector(checkModified)
    															 userInfo:nil
    															  repeats:YES];
    NSLog(@"monitoring start");
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    if (duration > 0)
    {
    	[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:duration]];
    }
    else
    {
    	[[NSRunLoop currentRunLoop] run];
    }
    NSLog(@"monitoring end");
    
    [pool release];

    return 0;
}
