/*
 *  PCTaskWrapper.h
 *
 *  Requires Mac OS X 10.3 or higher, PCUUID, and PCDebug
 *
 *
 *	Wraps a lot of the leg work of shelling out to NSTask, like collecting 
 * 	output and making sure a task dies, etc...
 *	
 *	NOTE: Some env variables are set to en_US.UTF-8, as this is the 
 *	default at the terminal (even in other languages), and helps when
 *	interpreting non-ASCII command line arguments. You can change it via
 *	setEnvironment if needed.
 *
 *	-------------------------------------------------------------------
 *
 *
 */

#import <Cocoa/Cocoa.h>

@class PCUUID;

// Cannot add more than PCTaskWrapperMaxArgs arguments for a given task or 
// it will crash.
#define PCTaskWrapperMaxArgs 4096

@interface PCTaskWrapper : NSObject 
{
@private
	NSTask* iTask;
	NSPipe* iStdoutPipe;
	NSPipe* iStderrPipe;
	NSMutableData* iStdoutBuffer;
	NSMutableData* iStderrBuffer;
	NSDictionary* iUserInfo;
	PCUUID* iUUID;
	NSLock* iKillLock;
	__weak id iDelegate;
	struct {
		BOOL matchesStdout;
		BOOL matchesStderr;
	} iDelegateFlags;
	NSArray* iStdoutMatchingData;
	NSArray* iStderrMatchingData;
	NSFileHandle* iStdoutLog;
	NSFileHandle* iStderrLog;
	NSConditionLock* iTerminationCallbackLock;
	NSMutableDictionary* iEnvironment;
}

@property(nonatomic, copy) NSDictionary* userInfo;
@property(nonatomic, readonly) PCUUID* UUID;
@property(nonatomic, assign) __weak id delegate;
@property(nonatomic, retain) NSFileHandle* stdoutLog;
@property(nonatomic, retain) NSFileHandle* stderrLog;
@property(nonatomic, readonly) NSString* launchPath;

// These properties allow the user to be called back if one of the data blobs in the given array is matched while reading the task output. If you set these to non-nil you MUST implement the corresponding delegate callback.
@property(copy) NSArray* stdoutMatchingData;
@property(copy) NSArray* stderrMatchingData;

- (id)initWithLaunchPath:(NSString*)aPath arguments:(NSArray*)someArguments;

- (NSArray*)arguments;

- (void)launch;
- (int)launchWaitUntilDone;
- (void)terminate;

- (void)setCurrentDirectoryPath:(NSString*)aPath;

- (NSDictionary*)environment;
- (void)setEnvironment:(NSDictionary*)anEnv;

- (NSString*)environmentForKey:(NSString*)aKey;
- (void)setEnvironment:(NSString*)aVal forKey:(NSString*)aKey;
- (void)removeEnvironmentForKey:(NSString*)aKey;

- (BOOL)isRunning;
- (PCUUID*)UUID;
- (NSData*)stdoutData;
- (NSData*)stderrData;
- (int)terminationStatus;

- (void)setStdin:(id)aStdin; // Either a pipe or a file handle

@end


@interface NSObject (PCTaskWrapperDelegate)

- (void)taskWrapperWillLaunch:(PCTaskWrapper*)aWrapper;
- (void)taskWrapperDidTerminate:(PCTaskWrapper*)aWrapper terminationStatus:(int)aStatus;

- (void)taskWrapper:(PCTaskWrapper*)aWrapper didMatchStdoutData:(NSData*)aData;
- (void)taskWrapper:(PCTaskWrapper*)aWrapper didMatchStderrData:(NSData*)aData;

@end
