//
//  CSHelperTool.h
//
//  Created by Chris Suter on 24/02/10.
//  Copyright 2010 Coriolis Systems Ltd. All rights reserved.
//

#ifndef CSHELPERTOOL_H_
#define CSHELPERTOOL_H_

#if __OBJC__

#import <Cocoa/Cocoa.h>

@class CSHelperCommand;
@class CSCondition;
@class SFAuthorization;

@protocol CSHelperToolDelegate

@optional;

- (void)helperToolCommand:(CSHelperCommand *)cmd
		 progress:(NSString *)progress;
- (void)helperToolCommandDidFinish:(CSHelperCommand *)cmd;

@end

@interface CSHelperCommand : NSObject {
  NSObject<CSHelperToolDelegate>  *delegate;

  NSString   *commandString;
  unsigned    commandID;
  int	      status;
  NSData     *data;
  BOOL	      fileDescriptorAvailable;
  BOOL	      progressOnMainThread;
  BOOL	      aborted;
  BOOL	      retainedDelegate;
  NSData     *_commandData;
}

+ (CSHelperCommand *)commandWithString:(NSString *)cmdString;
- (CSHelperCommand *)initWithString:(NSString *)cmdString;

- (NSString *)commandString;

@property (retain) NSData *commandData;

- (void)abort;

- (int)getFileDescriptor;

// Might return RET_NO_RESPONSE meaning a status isn't back yet
- (int)status;

// Blocks until a status is available
- (int)getStatus;

- (NSData *)data;

- (NSObject<CSHelperToolDelegate> *)delegate;
- (void)setDelegate:(NSObject<CSHelperToolDelegate> *)v;
- (void)retainDelegate;

- (BOOL)progressOnMainThread;
- (void)setProgressOnMainThread:(BOOL)v;

- (BOOL)aborted;

@end

@interface CSHelperTool : NSObject {
  NSString		*_helperPath;
  NSTask		*helperTask;
  int			 helperPipe;
  SFAuthorization	*authorization;
  int			*fdResult;
  CSCondition		*lock;
  NSMutableArray	*runningCommands;
  unsigned		 lastCommandID;
  BOOL			 receiveThreadRunning;
}

@property (copy) NSString *helperPath;

- (BOOL)startHelper;
- (void)terminateHelper;
+ (id)sharedInstance;
- (AuthorizationRef)authRef;
- (SFAuthorization *)authorization;

/* The commands below take strings with quoted arguments.  Use the methods
   in CSNSStringExtensions.h to build commands. */

// Main interface

- (BOOL)issue:(CSHelperCommand *)cmd;

// Convenience Methods

- (CSHelperCommand *)issueCommand:(NSString *)command
			 delegate:(NSObject<CSHelperToolDelegate> *)delegate;
- (int)performCommand:(NSString *)command
	     delegate:(NSObject <CSHelperToolDelegate> *)delegate
       fileDescriptor:(int *)fd
		 data:(NSData **)pdata;
- (int)performCommand:(NSString *)command;
- (int)performCommand:(NSString *)command
	     delegate:(NSObject <CSHelperToolDelegate> *)delegate;
- (int)performCommand:(NSString *)command
       fileDescriptor:(int *)fd;
- (int)performCommand:(NSString *)command
		 data:(NSData **)pdata;
- (CSHelperCommand *)issueCommand:(NSString *)command;

@end

#endif // __OBJC__

#import <stdlib.h>

/* C convenience methods so you can call from a file that's compiled as C */

typedef struct {
  int argc;
  const char **argv;
  int *pfd;
  void **pdata;
  size_t *plength;
  int (* progress_fn) (const char *progress, void *ctx);
  void *progress_ctx;
  size_t command_data_len;
  const void *command_data;
} helper_command_t;

int perform_helper_command (helper_command_t *command);

#endif // CSHELPERTOOL_H_
