/*
 *  Author:       Serg Stoyan
 *
 *  Class:        SessionWindow : NSObject
 *
 *  Description:  Window with PPP session selection. After connection is
 *                established shows statistics or PPP log information.
 *                Open and close connection.
 */

#import <Foundation/NSFileHandle.h>
#import <Foundation/NSNotification.h>

#import <AppKit/NSView.h>
#import <AppKit/NSWindow.h>
#import <AppKit/NSBox.h>
#import <AppKit/NSTextField.h>
#import <AppKit/NSSecureTextField.h>
#import <AppKit/NSPopUpButton.h>
#import <AppKit/NSButton.h>
#import <AppKit/NSImage.h>
#import <AppKit/NSScrollView.h>
#import <AppKit/NSTextView.h>
#import <AppKit/NSTextContainer.h>
#import <AppKit/NSTextStorage.h>

#import "AppController.h"
#import "AppIcon.h"
#import "AppDefaults.h"
#import "SessionWindow.h"
#import "PPPSession.h"

@implementation SessionWindow

- init
{
  NSView       *windowContentView;
  NSSize       svSize;
  NSRect       windowContentRect;
  unsigned int windowStyleMask;

  NSLog(@"SessionWindow open");

  // Initially no ppp session
  pppSession = nil;

  windowContentRect = NSMakeRect(0, 0, 300, 96);
  windowStyleMask = NSTitledWindowMask | NSResizableWindowMask;

  // Session Window 
  window = [[NSWindow alloc] 
    initWithContentRect: windowContentRect
    styleMask: windowStyleMask
    backing: NSBackingStoreRetained
    defer: YES];
  
  [window setTitle: @"Connect"];
  [window setReleasedWhenClosed: NO];
  [window setDelegate: self];
  [window setMaxSize: NSMakeSize (300, 380)];
  [window setMinSize: [NSWindow 
    frameRectForContentRect: windowContentRect
    styleMask: windowStyleMask].size];
  [window setResizeIncrements: NSMakeSize (0, 176)];
  windowContentView = [window contentView];

  // Session 
  sessionBox = [[NSBox alloc] initWithFrame: NSMakeRect(10, 44, 280, 42)];
  [sessionBox setTitlePosition: NSNoTitle];
  [sessionBox setAutoresizingMask: NSViewMinYMargin];
  [windowContentView addSubview: sessionBox];

  // Status Message Label
  statusMessage = [[NSTextField alloc] initWithFrame: 
    NSMakeRect(0, 3, 267, 21)];
  [statusMessage setAlignment: NSRightTextAlignment];
  [statusMessage setBackgroundColor: [NSColor windowBackgroundColor]];
  [statusMessage setSelectable: NO];
  [statusMessage setEditable: NO];
  [statusMessage setBezeled: NO];
  [statusMessage setBordered: NO];
//  [statusMessage setStringValue: @""];
  [statusMessage setFont: [NSFont boldSystemFontOfSize: 12.0]];
  [statusMessage setAlignment: NSCenterTextAlignment];
//  [[sessionBox contentView] addSubview: statusMessage];

  // Label
  sessionLabel = [[NSTextField alloc] initWithFrame: 
    NSMakeRect(0, 3, 58, 21)];
  [sessionLabel setAlignment: NSRightTextAlignment];
  [sessionLabel setBackgroundColor: [NSColor windowBackgroundColor]];
  [sessionLabel setSelectable: NO];
  [sessionLabel setEditable: NO];
  [sessionLabel setBezeled: NO];
  [sessionLabel setBordered: NO];
  [sessionLabel setStringValue: @"Session:"];
  [[sessionBox contentView] addSubview: sessionLabel];

  // Popup
  sessionPopup = [[NSPopUpButton alloc] initWithFrame:
    NSMakeRect(63, 3, 203, 21)];
  [sessionPopup setAutoenablesItems: NO];
  [[sessionBox contentView] addSubview: sessionPopup];
  [sessionPopup setAction: @selector (sessionPopupAction)];
  [sessionPopup setTarget: self];
  [self updateSessionsList];
  selectedSession = [sessionPopup titleOfSelectedItem];

  // Login as...
/*  loginBox = [[NSBox alloc] initWithFrame: NSMakeRect(10, 44, 280, 73)];
  [loginBox setTitle:@"Login As..."];
  [loginBox setAutoresizingMask: NSViewMinYMargin];
  [windowContentView addSubview: loginBox];

  usernameLabel = [[NSTextField alloc] initWithFrame: 
    NSMakeRect(0, 26, 58, 21)];
  [usernameLabel setAlignment: NSRightTextAlignment];
  [usernameLabel setBackgroundColor: [NSColor windowBackgroundColor]];
  [usernameLabel setSelectable: NO];
  [usernameLabel setEditable: NO];
  [usernameLabel setBezeled: NO];
  [usernameLabel setBordered: NO];
  [usernameLabel setStringValue: @"Username:"];
  [[loginBox contentView] addSubview: usernameLabel];

  usernameTF = [[NSTextField alloc] initWithFrame: 
    NSMakeRect(63, 26, 203, 21)];
  [[loginBox contentView] addSubview: usernameTF];

  passwordLabel = [[NSTextField alloc] initWithFrame: 
    NSMakeRect(0, 0, 58, 21)];
  [passwordLabel setAlignment: NSRightTextAlignment];
  [passwordLabel setBackgroundColor: [NSColor windowBackgroundColor]];
  [passwordLabel setSelectable: NO];
  [passwordLabel setEditable: NO];
  [passwordLabel setBezeled: NO];
  [passwordLabel setBordered: NO];
  [passwordLabel setStringValue: @"Password:"];
  [[loginBox contentView] addSubview: passwordLabel];

  passwordTF = [[NSSecureTextField alloc] initWithFrame:
    NSMakeRect(63, 0, 203, 21)];
  [[loginBox contentView] addSubview: passwordTF];

  // Linking text fields
  [usernameTF setNextText: passwordTF];
  [passwordTF setNextText: usernameTF];*/

  // Buttons
  connectButton = [[NSButton alloc] initWithFrame: 
    NSMakeRect(212, 10, 78, 24)];
  [connectButton setButtonType: NSMomentaryPushButton];
  [connectButton setTitle: @"Connect"];
/*  [connectButton setImagePosition: NSImageRight];
  [connectButton setImage: [NSImage imageNamed: @"common_ret"]];*/
  [connectButton setAction: @selector (connectAction)];
  [connectButton setTarget: self];
  [connectButton setAutoresizingMask: NSViewMinYMargin];
  [windowContentView addSubview: connectButton];

  detailsButton = [[NSButton alloc] initWithFrame: 
    NSMakeRect(10, 10, 78, 24)];
  [detailsButton setButtonType: NSMomentaryPushButton];
  [detailsButton setTitle: @"Details"];
  [detailsButton setImagePosition: NSImageRight];
  [detailsButton setImage: [NSImage imageNamed: @"common_ArrowDown"]];
  [detailsButton setAction: @selector (detailsAction)];
  [detailsButton setTarget: self];
  [detailsButton setAutoresizingMask: NSViewMinYMargin];
  [detailsButton setEnabled: NO];
  [windowContentView addSubview: detailsButton];

  // Details view
  detailsScroll = [[NSScrollView alloc] initWithFrame:
//    NSMakeRect(10, -2, 280, 2)];
    NSMakeRect(10, -178, 280, 178)];
  [detailsScroll setHasVerticalScroller: YES];
  [detailsScroll setHasHorizontalScroller: NO];
  [detailsScroll setBorderType: NSBezelBorder];
  [detailsScroll setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin];
  svSize = [detailsScroll contentSize];

  detailsText = [[NSTextView alloc] initWithFrame: 
    NSMakeRect(0, 0, svSize.width, svSize.height-4)];
  [detailsText setMaxSize: NSMakeSize(1e7, 1e7)];
  [detailsText setVerticallyResizable: YES];
  [detailsText setHorizontallyResizable: NO];
  [detailsText setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
  [detailsText setRichText: YES];
  [detailsText setSelectable: NO];
  [detailsText setEditable: NO];
  [detailsText setFont: [NSFont fontWithName: @"Courier" size: 10.0]];
  [[detailsText textContainer] setContainerSize:
    NSMakeSize(svSize.width, 1e7)];

  [detailsScroll setDocumentView: detailsText];
  [windowContentView addSubview: detailsScroll];

  RELEASE(sessionBox);
  RELEASE(sessionPopup);

/*  RELEASE(loginBox);
  RELEASE(usernameLabel);
  RELEASE(usernameTF);
  RELEASE(passwordLabel);
  RELEASE(passwordTF);*/

  RELEASE(connectButton);
  RELEASE(detailsButton);

  RELEASE (detailsText);
  RELEASE (detailsScroll);


  return self;
}

/*-------------------------------------------------------------------------*
 *  Window delegate methods
 *-------------------------------------------------------------------------*/
- (void) orderFront: (id)sender
{
//  [window makeFirstResponder: usernameTF];
//  [usernameTF lockFocus];
//  [window setContentSize: NSMakeSize (300, 272)];

  if (![window setFrameUsingName: @"SessionWindow"])
  {
    [window center];
  }
  [window orderFront: nil];

  [self addTextToDetailsView: @"Connect ready\n"];
}

- (void) dealloc
{
  NSLog(@"SessionWindow: dealloc");

  RELEASE(window);

  [super dealloc];
}

- (void) windowWillClose: (NSNotification *)notif
{
  NSLog(@"SessionWindow: will close");

  if (pppSession != nil)
  {
    [pppSession stop];
  }
  [window saveFrameUsingName: @"SessionWindow"];

  [self release];
}

/*-------------------------------------------------------------------------*
 *  Misc methods
 *-------------------------------------------------------------------------*/
- (NSString *) getSelectedSessionName
{
  if ([sessionPopup superview])
    return selectedSession;
  else
    return @"No sessions configured";
}

- (void) updateSessionsList
{
  NSArray *sessionsList = [[ConnectApp appDefaults] sessionsList];
  int     sessionsCount = [sessionsList count];
  int     i;
 
  [sessionPopup removeAllItems];
  if (sessionsCount <= 0)
  {
    [sessionPopup addItemWithTitle: @"No sessions configured"];
    selectedSession = [sessionPopup titleOfSelectedItem];
  }
  else
  {
    for (i = 0; i < sessionsCount; i++)
    {
      [sessionPopup addItemWithTitle: [sessionsList objectAtIndex: i]];
    }
    if ([sessionPopup indexOfItemWithTitle: selectedSession] >= 0)
    {
      [sessionPopup selectItemWithTitle: selectedSession];
    }
  }
}

/*-------------------------------------------------------------------------*
 *  Controls' action methods
 *-------------------------------------------------------------------------*/
- (void) sessionPopupAction
{
  BOOL sessionSame = [selectedSession isEqualToString: 
                                      [sessionPopup titleOfSelectedItem]];
    
  selectedSession = [sessionPopup titleOfSelectedItem];
  
  if (!sessionSame)
  {
    [ConnectApp configureSession: self];
  }
}

- (void) detailsAction
{
/*  NSRect winFrame = [window frame];
  NSRect winNewFrame = NSMakeRect (0, 0, 0, 0);
  
  if ([detailsButton image] == [NSImage imageNamed: @"common_ArrowDown"])
  {
    [detailsButton setImage: [NSImage imageNamed: @"common_ArrowUp"]];

    winNewFrame.origin.y = winFrame.origin.y - 176;
    winNewFrame.origin.x = winFrame.origin.x;
    winNewFrame.size.width = winFrame.size.width;
    winNewFrame.size.height = 380;
    [window setFrame: winNewFrame display: YES];
  }
  else
  {
    [detailsButton setImage: [NSImage imageNamed: @"common_ArrowDown"]];

    winNewFrame.origin.y = winFrame.origin.y + 176;
    winNewFrame.origin.x = winFrame.origin.x;
    winNewFrame.size.width = 300;
    winNewFrame.size.height = 204;
    [window setFrame: winNewFrame display: YES];
  }*/
}

- (void) connectAction
{
  if ([[connectButton stringValue] isEqualToString: @"Connect"])
  {
    [self clearDetailsView];
    [self addTextToDetailsView: @"Starting PPPSession...\n"];

    [self startPPPSession];

    [connectButton setStringValue: @"Disconnect"];
    [[ConnectApp appIcon] setMode: PPPOnMode];
  }
  else
  {
    if (pppSession != nil)
    {
      [pppSession stop];
    }
  }
}

/*-------------------------------------------------------------------------*
 *  Utility methods
 *-------------------------------------------------------------------------*/
- (void) clearDetailsView
{
  NSTextStorage *textStorage = [detailsText textStorage];
  NSRange       tvRange = NSMakeRange(0, [textStorage length]);

  // 0. Clear the contents of article view
  if (textStorage)
  {
    [textStorage deleteCharactersInRange: tvRange];
  }
}

- (void) addTextToDetailsView: (NSString *)text
{
  NSTextStorage      *textStorage = [detailsText textStorage];
  NSAttributedString *attributedText = nil;
  NSMutableString    *textString;

  // 1. append attributed text to the NSTextStorage of the NSTextView
  textString = [[NSMutableString alloc] initWithString: text];
//  [textString appendString: @"\n"];
  attributedText = [[NSAttributedString alloc] initWithString: textString];

  if ([textString length] > 0)
  {
    [textStorage appendAttributedString: attributedText];
  }

  [detailsText scrollRangeToVisible: 
    NSMakeRange ([textStorage length]-[textString length], [textString length])];

  RELEASE (attributedText);
}

@end

@implementation SessionWindow (Thread)

- (void) startPPPSession
{
  NSPort  *port1 = [NSPort new];
  NSPort  *port2 = [NSPort new];
  NSArray *portArray;

  // Create connection to PPPSession server
  mainConnection = [[NSConnection alloc] 
    initWithReceivePort: port1
    sendPort: port2];
  [mainConnection setRootObject: self];

  /* Ports switched here. */
  portArray = [NSArray arrayWithObjects: port2, port1, nil];

  NSLog (@"SessionWindow: detaching thread...");
  [NSThread 
    detachNewThreadSelector: @selector (connectWithPorts:)
    toTarget: [PPPSession class]
    withObject: portArray];

  // remove session popup and label
  RETAIN (sessionLabel);
  RETAIN (sessionPopup);
  [sessionLabel removeFromSuperview];
  [sessionPopup removeFromSuperview];

  // add status label
  [[sessionBox contentView] addSubview: statusMessage];
  RELEASE (statusMessage);

  return;
}

- (oneway void) finishPPPSession
{
  RELEASE (pppSession);
  pppSession = nil;

  // remove status label
  RETAIN (statusMessage);
  [statusMessage removeFromSuperview];

  // add session popup and label
  [[sessionBox contentView] addSubview: sessionLabel];
  [[sessionBox contentView] addSubview: sessionPopup];
  RELEASE (sessionLabel);
  RELEASE (sessionPopup);

  [self addTextToDetailsView: @"PPPSession finished...\n"];
  [[ConnectApp appIcon] setMode: PPPOffMode];
  [connectButton setStringValue: @"Connect"];
  [window setTitle: @"Connect"];

  return;
}

- (oneway void) statsPPPSession
{
  [[ConnectApp appIcon] setMode: PPPStatsMode];
}

- (oneway void) setServer: (id)anObject
{
  [anObject setProtocolForProxy: @protocol (PPPSessionMethods)];
  pppSession = [anObject retain];

  [pppSession start: selectedSession];
  [window setTitle: 
    [NSString stringWithFormat: @"Connecting to %@", selectedSession]];

  return;
}

- (oneway void) processServerText: (NSString *)text
{
  [self addTextToDetailsView: text];
}

- (oneway void) processStatusText: (NSString *)text
{
  [statusMessage setStringValue: text];
}

@end

