//
// $Id: ClientController.m,v 1.11 1997/10/31 04:51:38 nygard Exp $
//

//
//  This file is a part of Empire, a game of exploration and conquest.
//  Copyright (C) 1996  Steve Nygard
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//  You may contact the author by:
//     e-mail:  nygard@telusplanet.net
//

#import "Empire.h"

RCSID ("$Id: ClientController.m,v 1.11 1997/10/31 04:51:38 nygard Exp $");

#import "ClientController.h"

#import "Brain.h"
#import "DistributedGameManager.h"
#import "NewGameController.h"

//======================================================================
// Provides control over the connection to the server.  It also has
// to show the client player selection panel, and create the client
// game manager.
//======================================================================

@implementation ClientController

- (void) awakeFromNib
{
    [clientWindow setTitle:[NSString stringWithFormat:@"Client  %c  %@", 208, [[NSHost currentHost] name]]];

    empireServer = nil;
}

//----------------------------------------------------------------------

- initWithBrain:(Brain *)theBrain
{
    NSString *nibFile;
    BOOL loaded;

    [super init];

    nibFile = @"ClientWindow.nib";
    loaded = [NSBundle loadNibNamed:nibFile owner:self];
    if (loaded == NO)
    {
        NSLog (@"Could not load %@.", nibFile);
        [super dealloc];
        return nil;
    }

    brain = [theBrain retain];

    return self;
}

//----------------------------------------------------------------------

- (void) dealloc
{
    SNRelease (brain);
    
    [super dealloc];
}

//----------------------------------------------------------------------

- (void) showPanel
{
    [clientWindow makeKeyAndOrderFront:self];
}

//----------------------------------------------------------------------

- (void) connectAction:sender
{
    NSProtocolChecker *protocolChecker;

    // Note: When disconnected, the empireServer remains set... and probably shouldn't.
    NSAssert (empireServer == nil, @"Already connected.");

    // Note: The host should end up as @"*"...
  
    empireServer = [[NSConnection rootProxyForConnectionWithRegisteredName:SERVER_PORT_NAME
                                  host:[serverHostTextfield stringValue]] retain];

    NSAssert (empireServer != nil, @"Connection failed.");

    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector (connectionDidDie:)
                                          name:NSConnectionDidDieNotification
                                          object:[empireServer connectionForProxy]];

    [statusTextfield setStringValue:@"Connected."];

    serverConnection = [[empireServer connectionForProxy] retain];
    NSAssert (serverConnection != nil, @"serverConnection is nil.");
  
    [empireServer setProtocolForProxy:@protocol (EmpireServerConnectionProtocol)];

    protocolChecker = [NSProtocolChecker protocolCheckerWithTarget:self
                                         protocol:@protocol (EmpireClientConnectionProtocol)];
    NSAssert (protocolChecker != nil, @"A protocol checker could not be allocated.\n");

    NS_DURING
        {
            //[empireServer showText:@"Hello server, said the client."];
            [empireServer client:protocolChecker onHost:[[NSHost currentHost] name]];
            [empireServer ping];
        }
    NS_HANDLER
        {
            EHAND;
        }
    NS_ENDHANDLER;
}
  
//----------------------------------------------------------------------

- (void) disconnectAction:sender
{
    NSAssert (serverConnection != nil, @"Client not connected.");

    [empireServer aboutToDisconnect:self];
    
    [serverConnection invalidate];
    SNRelease (serverConnection);

    SNRelease (empireServer);

    //[statusTextfield setStringValue:@"Not connected."];
}
  
//----------------------------------------------------------------------

- (void) showText:(NSString *)format, ...
{
    NSMutableString *message;
    NSRange selected;
    va_list ap;

    va_start(ap, format);
    message = [[[NSMutableString alloc] initWithFormat:format arguments:ap] autorelease];
    [message appendString:@"\n"];
    va_end(ap);

    [messageText selectAll:nil];
    selected = [messageText selectedRange];
    selected.location = selected.length;
    selected.length = 0;
    [messageText setSelectedRange:selected];
    [messageText replaceCharactersInRange:selected withString:message];
    [messageText scrollRangeToVisible:selected];
}

//----------------------------------------------------------------------

- (void) ping
{
    [self showText:@"We were pinged..."];
}

//----------------------------------------------------------------------

- (void) aboutToDisconnect:sender
{
    [[sender connectionForProxy] invalidate];
}

//----------------------------------------------------------------------

- (void) connectionDidDie:(NSNotification *)notification
{
    [statusTextfield setStringValue:@"Not connected."];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                          name:nil
                                          object:[notification object]];
}

//----------------------------------------------------------------------

- (void) choosePlayer:(Player)number forMap:(Map *)worldMap master:masterGameManager
{
    DistributedGameManager *gameManager;
    NewGameController *newGameController;

    [masterGameManager setProtocolForProxy:@protocol (EmpireGameManagerProtocol)];

    gameManager = [[[DistributedGameManager alloc] init] autorelease];
    [gameManager startGameWithMap:worldMap master:masterGameManager];

    newGameController = [brain newGameController];
    [newGameController choosePlayer:number forGameManager:gameManager];
}

@end
