// Controller.m
//

#import "Controller.h"
#import "AGProcess.h"

NSString *stringForEnvironment(NSDictionary *env) {
	NSMutableString *str = [NSMutableString string];
	NSEnumerator *en = [env keyEnumerator];
	id key;
	while (key = [en nextObject])
		[str appendFormat:@"%@ = %@, ", key, [env objectForKey:key]];
	return str;
}
	
NSString *stringForState(int s) {
	switch (s) {
	default: return @"Unknown";
	case AGProcessStateUnknown: return @"";
	case AGProcessStateRunnable: return @"Runnable";
	case AGProcessStateUninterruptible: return @"Uninterruptible";
	case AGProcessStateSleeping: return @"Sleeping";
	case AGProcessStateIdle: return @"Idle";
	case AGProcessStateSuspended: return @"Suspended";
	case AGProcessStateZombie: return @"Zombie";
	case AGProcessStateExited: return @"Exited";
	}
}

NSString *stringForDouble(double value) {
	if (value != AGProcessValueUnknown)
		return [NSString stringWithFormat:@"%lf", value];
	else
		return @"Unknown";
}

NSString *stringForInt(int value) {
	if (value != AGProcessValueUnknown)
		return [NSString stringWithFormat:@"%d", value];
	else
		return @"Unknown";
}

@implementation Controller

- (void)awakeFromNib {
	refreshStatisticsTimer = [[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(refreshStatistics:) userInfo:nil repeats:YES] retain];
}

- (void)refreshStatistics:(id)sender {
	if ([[[browser selectedCell] representedObject] isKindOfClass:[AGProcess class]]) {
		AGProcess *process = [[browser selectedCell] representedObject];
		
		[commandCell setStringValue:[process command]];
		if ([process annotation])
			[annotationCell setStringValue:[process annotation]];
		else
			[annotationCell setStringValue:@""];
		[annotatedCommandCell setStringValue:[process annotatedCommand]];
		
		[processIdentifierCell setStringValue:stringForInt([process processIdentifier])];
		[parentProcessIdentifierCell setStringValue:stringForInt([process parentProcessIdentifier])];
		[processGroupCell setStringValue:stringForInt([process processGroup])];
		[userIdentifierCell setStringValue:stringForInt([process userIdentifier])];
		[realUserIdentifierCell setStringValue:stringForInt([process realUserIdentifier])];
		[terminalCell setStringValue:stringForInt([process terminal])];
		[terminalProcessGroupCell setStringValue:stringForInt([process terminalProcessGroup])];
		[percentCPUCell setStringValue:stringForDouble([process percentCPUUsage])];
		[totalCPUCell setStringValue:stringForDouble([process totalCPUTime])];
		[userCPUCell setStringValue:stringForDouble([process userCPUTime])];
		[systemCPUCell setStringValue:stringForDouble([process systemCPUTime])];
		if ([process percentMemoryUsage] != AGProcessValueUnknown)
			[percentMemoryCell setStringValue:stringForDouble([process percentMemoryUsage] * 100)];
		else
			[percentMemoryCell setStringValue:@"Unknown"];
		if ([process residentMemorySize] != AGProcessValueUnknown)
			[residentMemoryCell setStringValue:stringForDouble([process residentMemorySize] / (float)1048576)];
		else
			[residentMemoryCell setStringValue:@"Unknown"];
		if ([process residentMemorySize] != AGProcessValueUnknown)
			[virtualMemoryCell setStringValue:stringForDouble([process virtualMemorySize] / (float)1048576)];
		else
			[virtualMemoryCell setStringValue:@"Unknown"];
		[stateCell setStringValue:stringForState([process state])];
		if ([process priority] != AGProcessValueUnknown)
			[priorityCell setStringValue:[NSString stringWithFormat:@"%d/%d", [process priority], [process basePriority]]];
		else
			[priorityCell setStringValue:@"Unknown"];
		[threadsCell setStringValue:stringForInt([process threadCount])];

		[argumentsTextView setString:[[process arguments] componentsJoinedByString:@" "]];    
		[environmentTextView setString:stringForEnvironment([process environment])];     
	}
	else {
		[commandCell setStringValue:@""];
		[annotationCell setStringValue:@""];    
		[annotatedCommandCell setStringValue:@""];
		
		[processIdentifierCell setStringValue:@""];
		[parentProcessIdentifierCell setStringValue:@""];
		[processGroupCell setStringValue:@""];
		[terminalCell setStringValue:@""];
		[terminalProcessGroupCell setStringValue:@""];
		[userIdentifierCell setStringValue:@""];
		[realUserIdentifierCell setStringValue:@""];
		[percentCPUCell setStringValue:@""];
		[totalCPUCell setStringValue:@""];
		[userCPUCell setStringValue:@""];
		[systemCPUCell setStringValue:@""];
		[percentMemoryCell setStringValue:@""];
		[residentMemoryCell setStringValue:@""];
		[virtualMemoryCell setStringValue:@""];
		[stateCell setStringValue:@""];
		[priorityCell setStringValue:@""];
		[threadsCell setStringValue:@""];
		
		[argumentsTextView setString:@""];    
		[environmentTextView setString:@""];     
	}

}


@end

@implementation Controller (BrowserDelegate)

- (int)browser:(NSBrowser *)sender numberOfRowsInColumn:(int)column {
	if (column == 0)
		return 3;
	id representedObject = [[sender selectedCellInColumn:column - 1] representedObject];
	if ([representedObject isKindOfClass:[NSArray class]])
		return [representedObject count];
	else
		return 3;
}

- (void)browser:(NSBrowser *)sender willDisplayCell:(id)cell atRow:(int)row column:(int)column {
	
	if (column == 0) {
		switch (row) {
		case 0:
			[cell setStringValue:@"Current Process"];
			[cell setRepresentedObject:[NSArray arrayWithObject:[AGProcess currentProcess]]];
			break;
		case 1:
			[cell setStringValue:@"All Processes"];
			[cell setRepresentedObject:[AGProcess allProcesses]];
			break;
		case 2:
			[cell setStringValue:@"User Processes"];
			[cell setRepresentedObject:[AGProcess userProcesses]];
			break;
		}
	}
	else if (column % 2 != 0) {
		AGProcess *process = [[[sender selectedCellInColumn:column - 1] representedObject] objectAtIndex:row];
		[cell setStringValue:[process command]];
		[cell setRepresentedObject:process];
	}
	else {
		AGProcess *process = [[sender selectedCellInColumn:column - 1] representedObject];
		switch (row) {
		case 0:
			[cell setStringValue:@"Parent"];
			[cell setRepresentedObject:[NSArray arrayWithObject:[process parent]]];
			break;
		case 1:
			[cell setStringValue:@"Children"];
			[cell setRepresentedObject:[process children]];
			break;
		case 2:
			[cell setStringValue:@"Siblings"];
			[cell setRepresentedObject:[process siblings]];
			break;
		}
	}

}

- (BOOL)browser:(NSBrowser *)sender selectRow:(int)row inColumn:(int)column {
	[self refreshStatistics:self];
	return YES;
}

@end
