//
//  MPT_Distributed.m
//  MPT_Distributed
//
//  Created by Andrew Salamon on 7/2/08.
//  Copyright 2008 Machine Perception Laboratory, University of California San Diego.. All rights reserved.
//

#import "MPT_Distributed.h"

#import "MPT_DO_Server.h"
#import "MPT_DO_Client.h"

@implementation MPT_Distributed
- (id)initWithBundle:(NSBundle *)_bundle
{
	if( self = [super initWithBundle:_bundle] )
	{
		doClient = [[MPT_DO_Client alloc] init];
		doServer = [[MPT_DO_Server alloc] init];
		[self setPort:5860];
		if( ![NSBundle loadNibNamed:@"DistributedPrefView" owner:self] )
			NSLog( @"Unable to load pref pane for MPT_Distributed plugin." );
		[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clientDidShutdown:) name:[MPT_DO_Client shutdownNotificationName] object:doClient];
	}
	
	return self;
}

- (void)dealloc
{
	[[NSNotificationCenter defaultCenter] removeObserver:self];
	[doClient release];
	[doServer release];
	[super dealloc];
}

// It's not OK to copy this plugin, so return nil.
- (id)copyWithZone:(NSZone *)zone
{
	return nil;
}

- (NSString *)pluginID
{
	NSString *ident = [super pluginID];
	if( [ident length] > 0 )
		return ident;
	return @"edu.ucsd.mplab.plugins.Distributed";
}

- (NSString *)localizedName
{
	return NSLocalizedStringFromTableInBundle(@"CERT Distributed", nil, [self bundle], @"");
}

- (NSString *)internalName
{
	return @"distributed";
}

- (NSString *)step
{
	return MPT_PluginStep_Results;
}

- (NSView *)prefPane
{
	return prefView;
}

- (NSMutableDictionary *)processResults:(NSDictionary *)results usingController:(id<MPT_PluginControllerProtocol>)controller
{	
	return nil;
}

- (void)setEnabled:(BOOL)value
{
	if( value != [self enabled] )
	{
		[super setEnabled:value];
		// If we're no longer enabled, stop the client/server.
		if( !value )
			[self stop:self];
	}
}

- (void)setDelegate:(id)_delegate
{
	[super setDelegate:_delegate];
	[doServer setPluginController:_delegate];
	[doClient setPluginController:_delegate];
}

- (void)setScheduler:(id)value
{
	scheduler = value;
}

- (void)setAppDelegate:(id)value
{
	appDelegate = value;
	[doClient setDelegate:value];
}

- (BOOL)doesScheduleInput:(NSDictionary *)inputs
{
	if( [self enabled] && ![self isServer] && [self isRunning] )
	{
		[doClient scheduleInput:inputs];
		return YES;
	}
	return NO;
}

- (BOOL)isServer
{
    return isServer;
}

- (void)setIsServer:(BOOL)value
{
    isServer = value;
}

- (unsigned short)port
{
    return port;
}
- (void)setPort:(unsigned short)value
{
	if( 0 == value )
		port = 5860;
	else
		port = value;
}


- (NSString *)serverHost
{
    return serverHost;
}
- (void)setServerHost:(NSString *)value
{
    if( serverHost != value )
    {
        [serverHost release];
        serverHost = [value retain];
    }
}

- (IBAction)start:(id)sender
{
	[self setIsRunning:NO];
	if( isServer )
	{
		[doServer setScheduler:scheduler];
		if( ![doServer startWithPort:[self port]] )
			NSLog( @"Unable to start distributed server" );
		else
			[self setIsRunning:YES];
	}
	else
	{
		NSError *error = nil;
		@try
		{
			error = [doClient connectToServer:@"CERT" atHost:[self serverHost] port:[self port]];
		}
		@catch( NSException *exception )
		{
			NSLog( @"Unable to start distributed client: %@", [exception reason] );
			error = [NSError errorWithDomain:@"CERT_DO" code:5 userInfo:nil];
		}
		if( error )
			NSLog( @"Unable to start distributed client: %@", [error localizedDescription] );
		else
			[self setIsRunning:YES];
	}
}
- (IBAction)stop:(id)sender
{
	if( ![self isRunning] )
		return;
	
	if( isServer )
	{
		// If the server has a client connected, we should ask the user if they're sure they want to shut it down.
		[scheduler setDelegate:appDelegate];
		[doServer end];
	}
	else
	{
		[doClient cleanup];
	}
	[self setIsRunning:NO];
}

- (void)clientDidShutdown:(NSNotification *)notification
{
	[self setIsRunning:NO];
}

- (BOOL)isRunning
{
	return isRunning;
}
- (void)setIsRunning:(BOOL)value
{
	if( isRunning != value)
	{
		isRunning = value;
		[self setEnabled:YES];
	}
}

- (void)applicationWillTerminate:(NSNotification *)notification
{
#ifdef DEBUG
	NSLog( @"Distributed Plugin: App will terminate" );
#endif
	[self stop:self];
}

@end
