#import <c.h>
#import <stdlib.h>

#import <nikit/NIOpenPanel.h>

#import "NLoad.h"
#import "NLoadCommon.h"

#import "LoadView.h"
#import "RPCLoadView.h"
#import "UDPLoadView.h"

#define BORDER 3

#define PATH "/machines"
#define PROMPT "Host to monitor:"

#define DEFAULTSFILE "Defaults"

@implementation NLoad : Application

+ new
{
	unsigned int i;
	char pathnamebuf[MAXPATHLEN];

	self = [super new];

	bundle = [NXBundle bundleForClass:[self class]];
	
	if ([bundle getPath:pathnamebuf forResource:DEFAULTSFILE ofType:"strings"])

	[(defaults = [[DefaultsTable alloc] initFromFile:pathnamebuf]) registerDefaults:[self appName]];

	[[panel = [NIOpenPanel new] setDirectoryPath:PATH] setListTitle:PROMPT];
	
	[self getScreenSize:&size];

	location = origin = getPointDefault("Origin");
	increment = getPointDefault("Increment");

	switch((strncasecmp(getStringDefault("QueueLength"), "All", 1) == 0) ? ALL : getIntDefault("QueueLength")) {
		case 20: which[Q5MIN] = which[Q15MIN] = YES; break;
		case 21: which[Q5MIN] = YES;
		case 16: which[Q1MIN] = YES;
		case 15: which[Q15MIN] = YES; break;
		case  6: which[Q1MIN] = YES;
		case  5: which[Q5MIN] = YES; break;
		case  1: which[Q1MIN] = YES; break;
		default: for(i = 0; i < QUEUES; i++) which[i] = YES; break;
		}
		
	return self;
}

- appDidInit:sender
{
 	const char *string;
	NXRect cRect, fRect;
 	char *hostPtr, *nextHostPtr;
	id icon = [sender appIcon], aView;
	
	[icon getFrame:&fRect];

	[Window getContentRect:&cRect forFrameRect:&fRect style:[icon style]];

	cRect.origin.x = cRect.origin.y = BORDER;
	cRect.size.width -= BORDER * 2;
	cRect.size.height -= BORDER * 2;

	[[icon contentView] addSubview:(aView = [[LoadView alloc] initFrame:&cRect])];

	[self initializeView:aView];

	[[aView setUpdate:[localUpdateSlider floatValue]] startTimer];
	
	[[icon setBackgroundColor:[backgroundColorWell color]] display];

	if (*(string = getStringDefault("Hosts")) == '\0') return self;

	nextHostPtr = NXCopyStringBuffer(string);
 
	while (nextHostPtr != NULL) {
		hostPtr = nextHostPtr;
		if ((nextHostPtr = index(hostPtr, ';')) != NULL) *nextHostPtr++ = '\0';
		[self addHost:hostPtr];
		}

	return self;
}

- appWillTerminate:sender
{
	id list;
	BOOL flag = YES;
	unsigned int i, qLength = 0;
	
	if([localUpdateSlider tag]) (void) writeIntDefault("LocalUpdateSeconds", [localUpdateSlider intValue]);
	if([remoteUpdateSlider tag]) (void) writeIntDefault("RemoteUpdateSeconds", [remoteUpdateSlider intValue]);
	if([shiftDisplaySlider tag]) (void) writeDefault("ShiftDisplay", [shiftDisplaySlider stringValue]);
	
	if([q1ColorWell tag]) (void) writeColorDefault("Q1Color", [q1ColorWell color]);
	if([q5ColorWell tag]) (void) writeColorDefault("Q5Color", [q5ColorWell color]);
	if([q15ColorWell tag]) (void) writeColorDefault("Q15Color", [q15ColorWell color]);
	
	if([divisionColorWell tag]) (void) writeColorDefault("DivisionColor", [divisionColorWell color]);
	if([backgroundColorWell tag]) (void) writeColorDefault("BackgroundColor", [backgroundColorWell color]);
	if([quiescentColorWell tag]) (void) writeColorDefault("QuiescentColor", [quiescentColorWell color]);
	
	if([queueSwitchMatrix tag]) {
		list = [queueSwitchMatrix cellList];
		for(i = 0; i < QUEUES; i++) {
			if(which[i]) qLength += [[list objectAt:i] tag];
			else flag = NO;
			}
		if(flag) (void) writeDefault("QueueLength", "All");
		else (void) writeIntDefault("QueueLength", qLength);
		}
	
	return self;
}

- app:sender powerOffIn:(int) ms andSave:(int) aFlag
{
	if(aFlag) [self terminate:sender];

	return self;
}

- setDefault:sender { [sender setTag:YES]; return self; }

- setMatrixDefault:sender { [[sender selectedCell] setTag:YES]; return self; }

- setLocalUpdate:sender
{
	return [self setDefault:[localUpdateSlider setIntValue:[[localUpdateTextField setIntValue:[[sender selectedCell] intValue]] intValue]]];
}

- setRemoteUpdate:sender
{
	return [self setDefault:[remoteUpdateSlider setIntValue:[[remoteUpdateTextField setIntValue:[[sender selectedCell] intValue]] intValue]]];
}

- setDisplayShift:sender
{
	return [self setDefault:[shiftDisplaySlider setFloatValue:[[shiftDisplayTextField setFloatValue:[[sender selectedCell] floatValue]] floatValue]]];
}

- addHost:(const char *) string
{
	id aWindow, aView;
	NXRect cRect, fRect;
 	char *hostPtr, *namePtr, *sPtr, *typePtr;

	NXSetRect(&cRect, location.x, location.y, WIDTH, HEIGHT);
    [Window getFrameRect:&fRect forContentRect:&cRect style:NX_TITLEDSTYLE];

	aWindow = [[Window alloc] initContent:&cRect style:NX_TITLEDSTYLE
		backing:NX_BUFFERED buttonMask:NX_CLOSEBUTTONMASK defer:NO];

	namePtr = NXCopyStringBuffer(string);
	if ((sPtr = index(namePtr, '.')) != NULL) *sPtr = '\0';
	[aWindow setTitle:namePtr];
	free(namePtr);

	cRect.origin.x = cRect.origin.y = BORDER;
	cRect.size.width -= BORDER * 2;
	cRect.size.height -= BORDER * 2;

	hostPtr = NXCopyStringBuffer(string);
	if ((typePtr = rindex(hostPtr, ':')) != NULL && strcmp(typePtr, ":udp") == 0) {
		*typePtr = '\0';
		aView = [[UDPLoadView alloc] initFrame:&cRect];
		}
	else aView = [[RPCLoadView alloc] initFrame:&cRect];
	[aView setHostName:hostPtr];
	free(hostPtr);
	
	[self initializeView:aView];
	
	[[[aWindow setBackgroundColor:[backgroundColorWell color]] display] orderFront:nil];

	[[aWindow contentView] addSubview:aView];

	[[[aView setUpdate:[remoteUpdateSlider floatValue]] startTimer] display];
	
	location.x += (fRect.size.width * increment.x);
	if(location.x < 0.0 || (location.x + fRect.size.width) > size.width) {
		location.x = origin.x;
		location.y += (fRect.size.height * increment.y);
		}
	
	return self;
}

- addNIHost:sender
{
	if ([panel runModal] == NX_OKTAG) [self addHost:[panel directory]];

	return self;
}

- initializeView:aView
{
	unsigned int i;
	NXColor colors[QUEUES];

	for (i = 0; i < QUEUES; i++) colors[i] = [colorWells[i] color];

	[aView setQueueColors:colors];
	
	[[[aView setBackgroundColor:[backgroundColorWell color]] setQuiescentColor:[quiescentColorWell color]] setDivisionColor:[divisionColorWell color]];
	
	[[aView setShift:[shiftDisplaySlider floatValue]] setWhich:which];

	return self;
}

- setHelpPopUpList:anObject
{
	[[[(helpPopUpList = anObject) target] setTarget:self] setAction:@selector(displayHelp:)];
	
	return self;
}

- displayHelp:sender
{
	NXStream *stream;
	char pathnamebuf[MAXPATHLEN];

	if ([bundle getPath:pathnamebuf forResource:[[sender selectedCell] title] ofType:"rtf"]) {
		if ((stream = NXMapFile(pathnamebuf, NX_READONLY)) != NULL) {
			[helpScrollView readRichText:stream];
			NXCloseMemory(stream, NX_FREEBUFFER);
			}
		else return nil;
		}
	else return nil;

	return self;
}

- displayHelpWindow:sender
{
	[[helpScrollView window] makeKeyAndOrderFront:sender];

	return [self displayHelp:helpPopUpList];
}

- setQ1ColorWell:anObject
{
	[(colorWells[Q1MIN] = q1ColorWell = anObject) setColor:getColorDefault("Q1Color")];
	
	return self;
}

- setQ5ColorWell:anObject
{
	[(colorWells[Q5MIN] = q5ColorWell = anObject) setColor:getColorDefault("Q5Color")];
	
	return self;
}

- setQ15ColorWell:anObject
{
	[(colorWells[Q15MIN] = q15ColorWell = anObject) setColor:getColorDefault("Q15Color")];
	
	return self;
}

- setDivisionColorWell:anObject
{
	[(divisionColorWell = anObject) setColor:getColorDefault("DivisionColor")];
	
	return self;
}

- setBackgroundColorWell:anObject
{
	[(backgroundColorWell = anObject) setColor:getColorDefault("BackgroundColor")];
	
	return self;
}

- setQuiescentColorWell:anObject
{
	[(quiescentColorWell = anObject) setColor:getColorDefault("QuiescentColor")];
	
	return self;
}

- setLocalUpdateSlider:anObject
{ 
	[(localUpdateSlider = anObject) setIntValue:getIntDefault("LocalUpdateSeconds")];
	
	return self;
}

- setLocalUpdateTextField:anObject
{ 
	[(localUpdateTextField = anObject) setIntValue:getIntDefault("LocalUpdateSeconds")];
	
	return self;
}

- setRemoteUpdateSlider:anObject
{ 
	[(remoteUpdateSlider = anObject) setFloatValue:getFloatDefault("RemoteUpdateSeconds")];
	
	return self;
}

- setRemoteUpdateTextField:anObject
{ 
	[(remoteUpdateTextField = anObject) setIntValue:getIntDefault("RemoteUpdateSeconds")];
	
	return self;
}

- setShiftDisplaySlider:anObject
{ 
	[(shiftDisplaySlider = anObject) setFloatValue:getFloatDefault("ShiftDisplay")];
	
	return self;
}

- setShiftDisplayTextField:anObject
{ 
	[(shiftDisplayTextField = anObject) setFloatValue:getFloatDefault("ShiftDisplay")];
	
	return self;
}

- setQueueSwitchMatrix:anObject
{
	id list;
	int i, count;
	
	count = [(list = [(queueSwitchMatrix = anObject) cellList]) count];
	
	for(i = 0; i < count; i++) [[list objectAt:i] setIntValue:which[i]];
	
	return self;
}

- changeQueues:sender
{
	id list;
	int i, count;
	
	[sender setTag:YES];
	
	count = [(list = [sender cellList]) count];
	
	for(i = 0; i < count; i++) which[i] = [[list objectAt:i] intValue];
	
	return self;
}

- setVersion:anObject
{
	[(version = anObject) setStringValue:VERSION];
	
	return self;
}

@end
