//
//  PBEasyPipe.m
//  GitX
//
//  Created by Pieter de Bie on 16-06-08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "PBEasyPipe.h"


@implementation PBEasyPipe

+ (NSFileHandle*) handleForCommand: (NSString*) cmd withArgs: (NSArray*) args
{
	return [self handleForCommand:cmd withArgs:args inDir:nil];
}

+ (NSFileHandle*) handleForCommand: (NSString*) cmd withArgs: (NSArray*) args inDir: (NSString*) dir
{
	NSTask *task = [self taskForCommand:cmd withArgs:args inDir:dir];
	NSFileHandle* handle = [[task standardOutput] fileHandleForReading];
	
	[task launch];
	return handle;
}

+ (NSTask *) taskForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir
{
	NSTask* task = [[NSTask alloc] init];
	[task setLaunchPath:cmd];
	[task setArguments:args];
	if (dir) {
        // check if the dir exists and is really a folder
        BOOL isDir = NO;
        if ([[NSFileManager defaultManager] fileExistsAtPath:dir isDirectory:&isDir] && isDir) {
            [task setCurrentDirectoryPath:dir];
        }
    }
    
   /* use getenv too so we can easily use Xcodes executable environment */
	if (([[NSUserDefaults standardUserDefaults] boolForKey:@"Show Debug Messages"]) || (getenv("PBDebugEnabled"))) 
   {
      NSLog(@"Starting command `%@ %@` in dir %@", cmd, [args componentsJoinedByString:@" "], dir);
   }
   
#ifdef CLI
	NSLog(@"Starting command `%@ %@` in dir %@", cmd, [args componentsJoinedByString:@" "], dir);
#endif
    
	NSPipe* pipe = [NSPipe pipe];
	[task setStandardOutput:pipe];
    [task setStandardError:pipe];
	return task;
}

+ (NSString *) outputForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir retValue:(int *)ret {
    return [self outputForCommand:cmd withArgs:args inDir:dir byExtendingEnvironment:nil inputString:nil retValue:ret];
}

+ (NSString *) outputForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir inputString:(NSString *)input retValue:(int *)ret {
    return [self outputForCommand:cmd withArgs:args inDir:dir byExtendingEnvironment:nil inputString:input retValue:ret];
}

+ (NSString *) outputForCommand:(NSString *)cmd withArgs:(NSArray *)args inDir:(NSString *)dir byExtendingEnvironment:(NSDictionary *)dict inputString:(NSString *)input retValue:(int *)ret {
    NSTask * task = [self taskForCommand:cmd withArgs:args inDir:dir];

    if (dict) {
        NSMutableDictionary * env = [[[NSProcessInfo processInfo] environment] mutableCopy];
        [env addEntriesFromDictionary:dict];
        [task setEnvironment:env];
    }

    NSFileHandle * handle = [[task standardOutput] fileHandleForReading];

    if (input) {
        [task setStandardInput:[NSPipe pipe]];
        NSFileHandle * inHandle = [task.standardInput fileHandleForWriting];
        [inHandle writeData:[input dataUsingEncoding:NSUTF8StringEncoding]];
        [inHandle closeFile];
    }

    [task launch];

    NSData * data = [handle readDataToEndOfFile];
    NSString * string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    if (!string)
        string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];

    // Strip trailing newline
    if ([string hasSuffix:@"\n"])
        string = [string substringToIndex:[string length] - 1];

    [task waitUntilExit];
    if (ret)
        *ret = [task terminationStatus];
    return string;
}	

// We don't use the above function because then we'd have to wait until the program was finished
// with running

+ (NSString*) outputForCommand: (NSString*) cmd withArgs: (NSArray*) args  inDir: (NSString*) dir
{
	NSTask *task = [self taskForCommand:cmd withArgs:args inDir:dir];
	NSFileHandle* handle = [[task standardOutput] fileHandleForReading];
	
	[task launch];
	NSData *data;
	@try {
		data = [handle readDataToEndOfFile];
	}
	@catch (NSException * e) {
		NSLog(@"Got a bad file descriptor in %s!", _cmd);
		if ([NSThread currentThread] != [NSThread mainThread])
			[task waitUntilExit];

		return nil;
	}
	NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
	if (!string)
		string = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
	
	// Strip trailing newline
	if ([string hasSuffix:@"\n"])
		string = [string substringToIndex:[string length]-1];

	if ([NSThread currentThread] != [NSThread mainThread])
		[task waitUntilExit];

	return string;
}


+ (NSString*) outputForCommand: (NSString*) cmd withArgs: (NSArray*) args
{
	return [self outputForCommand:cmd withArgs:args inDir:nil];
}

@end
