/* Writed by Averous Julien-Pierre, www.sourcemac.com */


#import "Controller.h"

@implementation Controller

/*
** Init our controller
*/
- (id)init
{
	if(self = [super init])
		{
		tsk = nil;
		pathString = nil;
		sock = -1;
		baseHeight = 90;
		ids = [[NSMutableArray alloc] init];
		}
	
	return self;
}


/*
** User select a soft
*/
- (IBAction)LoadSoft:(id)sender
{
	NSOpenPanel *panel=[NSOpenPanel openPanel];
		
	[panel setCanChooseFiles:YES];
	[panel setCanChooseDirectories:NO];
	[panel setAllowsMultipleSelection:NO];
	[panel setShowsHiddenFiles:YES];
	
	[panel beginSheetForDirectory:nil
		   file:nil
		   types:nil
		   modalForWindow:win
		   modalDelegate:self
		   didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
		   contextInfo:nil
		   ];
}


/*
** User want to run the soft
*/
- (IBAction)Com_Run:(id)sender
{
	NSDictionary	*env;
	NSBundle		*bnd = [NSBundle mainBundle];
	
	if(tsk)
		{
		[tsk terminate];
		[tsk release];
		}
	tsk = [[NSTask alloc] init];
	[tsk setLaunchPath:pathString];
	
	env = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[bnd pathForResource:@"mallocdeb" ofType:@"dynlib"], @"", nil]
									  forKeys:[NSArray arrayWithObjects:@"DYLD_INSERT_LIBRARIES", @"DYLD_FORCE_FLAT_NAMESPACE", nil]];
	
	[tsk setEnvironment:env];
	[tsk setArguments:[[com_run_args stringValue] componentsSeparatedByString:@" "]];
	[tsk launch];

	[self loadCommunication];
}


/*
** User want exit
*/
- (IBAction)Com_Exit:(id)sender
{
	send(sock, "=EXIT=", 6, 0);
}

/*
** User want count frame
*/
- (IBAction)Com_Cont:(id)sender
{
	send(sock, "=CONT=", 6, 0);
}

/*
** User want get alloc size
*/
- (IBAction)Com_Gasz:(id)sender
{
	send(sock, "=GASZ=", 6, 0);
}

/*
** User want get free size
*/
- (IBAction)Com_Gfsz:(id)sender
{
	send(sock, "=GFSZ=", 6, 0);
}

/*
** User want get leak size
*/
- (IBAction)Com_Glsz:(id)sender
{
	send(sock, "=GLSZ=", 6, 0);
}

/*
** User want list IDs
*/
- (IBAction)Com_List:(id)sender
{
	send(sock, "=LIST=", 6, 0);
}

/*
** User want get maximum ID match
*/
- (IBAction)Com_Mxid:(id)sender
{
	send(sock, "=MXID=", 6, 0);
}

/*
** User want get size of a frame, with it's ID
*/
- (IBAction)Com_Size:(id)sender
{
	sprintf(buffer, "=SIZE=%i\n", [com_size_id intValue]);
	send(sock, buffer, strlen(buffer), 0);
}


- (IBAction)Com_Dump:(id)sender
{
	sprintf(buffer, "=DUMP=%i\n", [com_dump_all intValue] ? -1 : [com_dump_id intValue]);
	send(sock, buffer, strlen(buffer), 0);
}

- (IBAction)Com_Dump_All:(id)sender
{
	[com_dump_id setEnabled:![sender state]];
}


/*
** Open panel was closed
*/
- (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
	NSArray		*arr=[panel filenames];
	NSBundle	*bnd;
	
	if(!arr || [arr count] <= 0 || returnCode == NSCancelButton)
		return;
	
	if(pathString)
		[pathString release];
	
	bnd = [NSBundle bundleWithPath:[arr objectAtIndex:0]];
	
	if (bnd)
		pathString = [[bnd executablePath] retain];
	else
		pathString = [[arr objectAtIndex:0] retain];
	
	[softPath setStringValue:pathString];
	[softPath setEnabled:1];
}






/*
** Run the communication between us and the soft
*/
- (void)loadCommunication
{
	struct sockaddr_in	dest_addr;
	int					err = 1;
	
	/*
	  Configure the "to" server port & adress
	*/
	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(65000);
	dest_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
	memset(&(dest_addr.sin_zero), '\0', 8);
	
	while (err)
		{
		usleep(100000);
		err = 0;
		
		/*
		  Instanciate an fd for the connection
		*/
		if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
			return [self comError];
		/*
		  Make the connexion
		*/
		if (connect(sock, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr)) == -1)
			err = 1;
		}

	[NSApplication detachDrawingThread:@selector(runSockRunLoop:) toTarget:self withObject:nil];
}


/*
** Communication error
*/
- (void)comError
{
	if (tsk)
		{
		[tsk terminate];
		[tsk release];
		tsk = nil;
		}
	
	if (sock != -1)
		{
		NSBeep();
		NSLog(@"Communication error / ended");
		close(sock);
		sock = -1;
		}
	
	[softPath setStringValue:@"-"];
}

/*
** Socket run loop
*/
- (void)runSockRunLoop:(id)obj
{
	int	sz;
	int	v;
	
	while ((sz = recv(sock, buffer, sizeof(buffer) - 1, 0)) > 0)
		{
		if (sz < 6)
			continue;
		buffer[sz] = '\0';
		if (sz > 0 && buffer[sz - 1] == '\n')
			buffer[sz - 1] = '\0';
		
		if (strncmp(buffer, "=WELC=", 6) == 0)
			[com_run setStringValue:[NSString stringWithUTF8String:buffer + 6]];
		
		if (strncmp(buffer, "=CONT=", 6) == 0)
			{
			v = atoi(buffer + 6);
			[com_cont setIntValue:v];
			}
		
		if (strncmp(buffer, "=MXID=", 6) == 0)
			{
			v = atoi(buffer + 6);
			[com_mxid setIntValue:v];
			}
		
		if (strncmp(buffer, "=LIST=", 6) == 0)
			{
			NSArray* arr = [[NSString stringWithUTF8String:buffer] componentsSeparatedByString:@"\n"];
			int i, cnt = [arr count];

			for (i = 0; i < cnt; i++)
				{
				NSArray* aarr = [[arr objectAtIndex:i] componentsSeparatedByString:@"=LIST="];
				if ([aarr count] > 1 && ![[aarr objectAtIndex:1] isEqualToString:@"=ENDL="])
					[ids addObject:[aarr objectAtIndex:1]];
				}
			[com_list reloadData];
			}
		
		if (strncmp(buffer, "=SIZE=", 6) == 0)
			{
			v = atoi(buffer + 6);
			[com_size setIntValue:v];
			}
		
		if (strncmp(buffer, "=GASZ=", 6) == 0)
			{
			v = atoi(buffer + 6);
			[com_gasz setIntValue:v];
			}
		
		if (strncmp(buffer, "=GFSZ=", 6) == 0)
			{
			v = atoi(buffer + 6);
			[com_gfsz setIntValue:v];
			}
		
		if (strncmp(buffer, "=GLSZ=", 6) == 0)
			{
			v = atoi(buffer + 6);
			[com_glsz setIntValue:v];
			}
		
		if (strncmp(buffer, "=DUMP=", 6) == 0)
			{
			NSString* str = [NSString stringWithUTF8String:buffer + 6];
			
			if ([str isEqualToString:@"=0505="])
				[com_dump setStringValue:@"Can't make dump file"];
			else if ([str isEqualToString:@"=0404="])
				[com_dump setStringValue:@"Unknow ID"];
			else
				[com_dump setStringValue:[NSString stringWithFormat:@"File dump : \"%@\"", str]];
			}
					
		if (strncmp(buffer, "=EXIT=", 6) == 0)
			{
			buffer[11] = 0;
			v = atoi(buffer + 7);
			
			if (v == 300)
				[com_exit setStringValue:@"User want exit"];
			if (v == 200)
				[com_exit setStringValue:@"Exit well sent"];
			}
		
		if (strncmp(buffer, "=SERR=", 6) == 0)
			NSLog([NSString stringWithUTF8String:buffer + 6]);
		
		}
	
	[self comError];
}



/* ID List manage */
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
	return [ids count];
}

- (id)tableView:(NSTableView *)aTableView
    objectValueForTableColumn:(NSTableColumn*)aTableColumn
    row:(int)rowIndex
{
	if (rowIndex < 0)
		return @"";

	return [ids objectAtIndex: rowIndex];
}

@end
