#import "NetTalkThinker.h"
#import "NetTalkClient.h"
#import "OpenTalk.h"
#import "TalkController.h"
#import "MiscCode.subproj/MailSpeaker.h"
#import "MiscCode.subproj/MiscEmacsText.h"
#import <appkit/appkit.h>
#import <objc/objc-runtime.h>
#import <sys/types.h>
#import <ansi/ctype.h>
#import <bsd/pwd.h>

#define		NXLS(bla) NXLocalizedString(bla, 0, 0)

@implementation NetTalkThinker

+ initialize
{
	static NXDefaultsVector NetTalkDefaults =
	{{NTD_AUTOLAUNCH, "YES"},
	 {NTD_MUTEALARM, "NO"},
	 {NTD_SOUNDNAME, "Ring.snd"},
	 {NTD_RINGSOUNDNAME, "Ring.snd"},
	 {NTD_RINGINGALLOWED, "YES"},
	 {NTD_SERVERLIST, "goanna.mpi-hd.mpg.de trantor.oph.rwth-aachen.de"},
	 {NTD_USESELECTED, "YES"},
	 {NTD_DEFAULTTOPIC, "blafasel"},
	 {NTD_NETNAME, ""},
	 {NULL, NULL}};

	NXRegisterDefaults(APPNAME, NetTalkDefaults);
	[MiscEmacsText poseAs:[Text class]];

	return self;
}

- (BOOL)setPort
{
	/* Should call this before any remote message to make sure Mail.app is
	/ running and mailSpeaker 's port is current.  Get named port ' Mail '.  
	/ This will launch Mail.app if not already.Get named port 'MailSendDemo'
  / (this is the one we will actually talk to).Set mailSpeaker 's port to be this one. 
	*/

	port_t              mailPort = NXPortFromName("Mail", NULL);

	if (mailPort == PORT_NULL)
	{
		NXRunLocalizedAlertPanel(NULL
			, "Accessing Mail", "Unable to connect to Mail.app"
			, NULL, NULL, NULL);
		return NO;
	}

	mailPort = NXPortFromName("MailSendDemo", NULL);

	if (mailPort == PORT_NULL)
	{
		(NXRunLocalizedAlertPanel(NULL
			, "Accessing Mail", "Unable to connect to Mail.app"
			, NULL, NULL, NULL));
		return NO;
	}

	[mailSpeaker setSendPort:mailPort];
	return YES;
}

- sendComments:sender
{
	char       body[4096];
	int        winNum;

	if ([self setPort])
	{
		sprintf(body, (const char *)NXLS("msg_comments")
			, NTKVERSION, [client realUserName]);
		[mailSpeaker openSend:&winNum];
		[mailSpeaker setTo:NXLS("to_address") inWindow :winNum];
		[mailSpeaker setSubject:NXLS("msg_nettalk") inWindow :winNum];
		[mailSpeaker setBody:(const char *)body inWindow:winNum];
	}
	return self;
}

- (BOOL)closeActive:menuCell
{
	BOOL                shouldBeEnabled;

	shouldBeEnabled = [[[NXApp mainWindow] delegate]
										 isKindOf:[TalkController class]];

	if ([menuCell isEnabled] != shouldBeEnabled)
	{
		[menuCell setEnabled:shouldBeEnabled];
		return YES;									/* redisplay */
	}
	return NO;										/* no change */
}

- (BOOL)stayAboveActive:menuCell
{
	BOOL shouldBeEnabled;
	id   controller = [[NXApp mainWindow] delegate];
	
	shouldBeEnabled = [controller isKindOf:[TalkController class]];
	if ([controller windowIsStayAbove])
		[menuCell setTitle:NXLS("Normal")];
	else
		[menuCell setTitle:NXLS("Stay above")];
	[menuCell setEnabled:shouldBeEnabled];
	return YES;
}


- free
{
	[super free];
	[requestList free];
	return self;
}


- client
{
	return client;
}


- showInfoPanel:sender
{
	if (!infoPanel)
	{		
		if ([NXApp loadNibSection:"Info.nib" owner:self withNames:NO] == nil)
			return nil;
		[infoPanel center];
	}
			
	[infoPanel makeKeyAndOrderFront:sender];
	[versionField setStringValue:NTKVERSION];
	
 	return self;
}

- showPrefPanel:sender
{
	if (!prefPanel)
	{
		if ([NXApp loadNibSection:"Preferences.nib" owner:self withNames:NO] == nil)
			return nil;
		[prefPanel setFrameAutosaveName:"Preferences"];
	}
	
	[prefPanel makeKeyAndOrderFront:sender];
	
 	return self;
}

- showRequestPanel:sender
{
	if (!requestPanel)
	{
		return nil;
		/* this shouldn't happen, because the panel is in NetTalk.nib! */
	}
	[requestPanel makeKeyAndOrderFront:sender];

 	return self;
}

- setRequest:sender
{
	BOOL         flag;
	TalkRequest *theRequest;
	Window      *talkWindow = nil;
	
	flag = ([requestBrowser selectedCell] != nil);
	theRequest = [requestList objectAt:
		[[requestBrowser matrixInColumn:0] selectedRow]];
	talkWindow = [NXApp mainWindow];
	if (![[talkWindow delegate] isKindOf:[TalkController class]])
		talkWindow = nil;
	[refuseButton setEnabled:flag];
	[insertButton setEnabled:(talkWindow && flag)];
	[connectButton setEnabled:flag];
	if (theRequest)
		[topicText setStringValue:[theRequest requestTopic]];
	else
		[topicText setStringValue:""];
	[requestPanel display];
	return self;
}

- openTalk:sender
{
	OpenTalk               *openTalk = [OpenTalk new];
	char                    aClientUName[MAXPATHLEN];
	Window                 *newWindow;
	
	[openTalk setupPopupFrom:bundleList];
	[openTalk setDelegate:self];
	[openTalk setClassName:[currentControllerClass name]];
	[openTalk setServerName:[client serverName]];
	openTalkPanel = openTalk;
	if ([openTalk runModal] == NX_OKTAG)
	{
		if ([self getUniqueName:aClientUName at:[openTalk clientNumber]]
				== NT_NOCLIENT)
			return nil;
		if (([openTalk topic])
			&& (newWindow = [self connectionForTopic:[openTalk topic]]))
		{
			[newWindow makeKeyAndOrderFront:nil];
			[client
				sendConnectTo:aClientUName
				via:[[newWindow delegate] document]
				withCode:[[newWindow delegate] connectionCode]
				topicIs:[openTalk topic]];
			[[newWindow delegate] markClientUNameInvited:aClientUName
				forCode:[[newWindow delegate] connectionCode]];
		}
		else
		{
			TalkController   *controller;
			
			currentControllerClass = objc_lookUpClass([openTalk className]);
			if (controller = [currentControllerClass newFromNib])
			{
				const char *topic = [openTalkPanel topic];
				
				[controller setup];
				[controller setTopic:topic];
				[client 
					sendConnectTo:aClientUName 
					via:[controller document]
					withCode:[controller connectionCode]
					topicIs:topic];
				[controller markClientUNameInvited:aClientUName
					forCode:[controller connectionCode]];
			}
		}
	}
	openTalkPanel = nil;
	return self;
}


@end


@implementation NetTalkThinker(BrowserDelegate)

- (int)browser:sender getNumRowsInColumn:(int)column
{
	if ([requestList count] == 0)
		[self _display:[imageList objectAt:0]];
	return [requestList count];
}

- browser:sender loadCell:cell atRow:(int)row inColumn:(int)column
{
	char         title[1024];
	TalkRequest *theRequest = [requestList objectAt:row];
	const char  *topic = [theRequest requestTopic];
	const char  *clientName;

	clientName = [[[client server]
		findClientNamed:[theRequest requestUName]] clientName];
	if ((topic) && (topic[0]))
	{
		sprintf(title, "%s: %s", clientName, topic);
	}
	else
		strcpy(title, clientName);
	[cell setStringValue:title];
	[cell setLoaded:YES];
	[cell setLeaf:YES];
	[cell setEnabled:YES];

	return self;
}

@end


@implementation NetTalkThinker(ApplicationDelegate)

- appDidInit:sender
{
	const char  *value;
	id           connectionMenu = [connectionSubmenuCell target];
	id           windowMenu = [windowsSubmenuCell target];

	/*  load bundles containing talk stuff  */
	[self initializeBundles:NXApp];

	/* Setting the AutoUpdate Messages for the MenuCells */
	[conncloseCell setUpdateAction:@selector(closeActive:)
	 forMenu :connectionMenu];
	[winCloseCell setUpdateAction:@selector(closeActive:)
	 forMenu :windowMenu];
	[stayAboveCell setUpdateAction:@selector(stayAboveActive:)
	 forMenu :windowMenu];
	[NXApp setAutoupdate:YES];
	
	imageList = [[List alloc] init];
	[imageList insertObject: [NXImage findImageNamed: "NetTalk"] at: 0];
	[imageList insertObject: [NXImage findImageNamed: "OSTring1"] at: 1];
	[imageList insertObject: [NXImage findImageNamed: "OSTring2"] at: 2];
	[imageList insertObject: [NXImage findImageNamed: "OSTring3"] at: 3];

	appTile = [NXImage findImageNamed: "NXAppTile"];
	appIconContentView = [[NXApp appIcon] contentView];
	
	client = [[NetTalkClient alloc] init];
	if (!client)
	{
		[NXApp setDelegate:nil];
		[NXApp terminate:nil];
	}
	[client setDelegate:self];
	
/* read defaults */
	[[requestBrowser window] setFrameAutosaveName:"RequestPanel"];

	if (value = NXGetDefaultValue([NXApp appName], "ShowRequestPanel"))
		if (strcmp(value, "YES") == 0)
			[[requestBrowser window] makeKeyAndOrderFront:nil];

	if (!strcmp(NXGetDefaultValue([NXApp appName], "NXAutoLaunch"), "YES")
			&& !strcmp(NXGetDefaultValue(APPNAME, NTD_AUTOLAUNCH), "YES"))
		[NXApp hide:self];

	value = NXGetDefaultValue(APPNAME, NTD_SOUNDNAME);
	if (strrchr(value, '/') == NULL)
	{
		char   path[MAXPATHLEN];
		[[NXBundle mainBundle] getPath:path forResource:value ofType:NULL];
		NXSetDefault(APPNAME, NTD_SOUNDNAME, path);
	}

	value = NXGetDefaultValue(APPNAME, NTD_RINGSOUNDNAME);
	if (strrchr(value, '/') == NULL)
	{
		char   path[MAXPATHLEN];
		[[NXBundle mainBundle] getPath:path forResource:value ofType:NULL];
		NXSetDefault(APPNAME, NTD_RINGSOUNDNAME, path);
	}

	requestList = [[List alloc] initCount:0];
	[requestBrowser setAction:@selector(setRequest:)];
	[requestBrowser setDoubleAction:@selector(connect:)];
	[[requestBrowser window] setBecomeKeyOnlyIfNeeded:YES];

	return self;
}

- appWillTerminate:sender
{
	int       count;
	id        window;

	count = [[NXApp windowList] count];
	while (count--)
	{
		window = [[NXApp windowList] objectAt:count];
		if ([[window delegate] isKindOf:[TalkController class]])
			[[window setDocEdited:NO] performClose:self];
	}
	[[client server] removeClient:client];
	
	if ([[requestBrowser window] isVisible])
		NXWriteDefault([NXApp appName], "ShowRequestPanel", "YES");
	else
		NXWriteDefault([NXApp appName], "ShowRequestPanel", "NO");
	NXUpdateDefaults();
	return self;
}

@end

