/*
**  PlopWindowController.m
**
**  Copyright (c) 2002
**
**  Author: Ludovic Marcotte <ludovic@Sophos.ca>
**
**  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.
*/

#import "PlopWindowController.h"

#import "Channel.h"
#import "Constants.h"
#import "NSStringExtensions.h"
#import "Plop.h"
#import "PlopView.h"
#import "PlopWindow.h"

static id lastPlopWindowOnTop = nil;

@implementation PlopWindowController

- (id) initWithWindowNibName: (NSString *) theNibName
{
  PlopWindow *plopWindow;
  
  plopWindow = [[PlopWindow alloc] initWithContentRect:NSMakeRect(10,10,DEFAULT_PLOP_WIDTH,DEFAULT_PLOP_HEIGHT)
				   styleMask: NSBorderlessWindowMask
                                   backing: NSBackingStoreBuffered
                                   defer: NO];

  self = [super initWithWindow: plopWindow];
  RELEASE(plopWindow);
 
  [plopWindow layoutWindow];
  [plopWindow setDelegate: self];

  // We link our outlets
  textView = [plopWindow textView];


  // We set our text view color
  [textView setBackgroundColor: [NSColor colorWithDeviceRed: 0.90
					 green: 0.90
					 blue: 0.90
					 alpha: 1.0]];
  
  // We set the title to an empty string
  [[self window] setTitle: @""];

#ifdef MACOSX
  // We link the dock menu
  dockMenu = [[NSApp delegate] applicationDockMenu: nil];
#endif  

  return self;
}


//
//
//
- (void) dealloc
{
  NSLog(@"PlopWindowController: -dealloc");

  lastPlopWindowOnTop = nil;
  
  [channel setPlopWindowController: nil];
  RELEASE(channel);

#ifdef MACOSX
  RELEASE(dockSubMenu);
#endif

  [super dealloc];
}



//
// delegate methods
//
- (BOOL) textView: (NSTextView *) textView
    clickedOnLink: (id) link 
	  atIndex: (unsigned) charIndex
{
  return [self openURL: link];
}


//
//
//
- (void) windowDidBecomeKey: (NSNotification *) aNotification
{
  lastPlopWindowOnTop = [self window];
  //[[PlopInfoWindowController singleInstance] setPlop: [self plop]];
}


//
//
//
- (void) windowDidLoad
{
  lastPlopWindowOnTop = [self window];
  
  [super windowDidLoad];
}


//
//
//
- (void) windowDidMove: (NSNotification *) aNotification
{
  [self _updateWindowFrame];
}


//
//
//
- (void) windowDidResize: (NSNotification *) aNotification
{
  [self _updateWindowFrame];
}


//
//
//
- (void) windowWillClose: (NSNotification *) theNotification
{
  AUTORELEASE(self);
}


//
// access / mutation
//
+ (id) lastPlopWindowOnTop
{
  return lastPlopWindowOnTop;
}


//
//
//
- (Channel *) channel
{
  return channel;
}


//
//
//
- (void) setChannel: (Channel *) theChannel
{
  if ( theChannel )
    {
      RETAIN(theChannel);
      RELEASE(channel);
      channel = theChannel;

      [channel setPlopWindowController: self];
      
      // We set our count variable and our icon
      [[self plopView] setCount: [channel itemCount]];
      [[self plopView] setIcon: [channel icon]];
      
      // We now update the text view with the content of the channel
      [self update];

      // We finally set the window title and frame
      if ( [channel title] )
        {
          [[self window] setTitle: [channel title]];
        }
      [[self window] setFrame: [[channel plop] frame]
		     display: NO];

#ifdef MACOSX
      // We create a submenu in the dock menu
      [dockMenu addItemWithTitle: [[channel plop] title] action: nil keyEquivalent: @""];
      dockSubMenu = [[NSMenu alloc] init];
      [dockMenu setSubmenu: dockSubMenu forItem: [dockMenu itemWithTitle: [[channel plop] title]]];
#endif
    }
  else
    {
      RELEASE(channel);
      channel = nil;
    }
}


//
//
//
- (NSTextView *) textView
{
  return textView;
}


//
//
//
- (PlopView *) plopView
{
  return [(PlopWindow *)[self window] plopView];
}


//
// action methods
//
#ifdef MACOSX
- (IBAction) dockItemSelected: (id) sender
{
    if ( [sender isKindOfClass: [NSMenuItem class]] )
    {
        [self openURL: (NSURL *)[(NSMenuItem *)sender representedObject]];
    }
}


- (IBAction) dockItemUpdate: (id) sender
{

    if ( [sender isKindOfClass: [NSMenuItem class]] )
    {
        [channel update: [self plopView]];
    }
}
#endif


//
// Other methods
//
- (BOOL) openURL: (NSURL *) theURL
{
  NSLog(@"Opening %@...", [theURL description]);

  if ( [[NSUserDefaults standardUserDefaults] integerForKey: @"BROWSER_SOURCE"] == USE_DEFAULT_BROWSER )
    {
      return [[NSWorkspace sharedWorkspace] openURL: theURL];
    }
  else
    {
      NSString *handler;

      handler = [[NSUserDefaults standardUserDefaults] objectForKey: @"BROWSER_PATH"];

      if ( !handler || [[handler stringByTrimmingWhiteSpaces] length] == 0 )
	{
	  NSBeep();
	  return NO;
	}
      
      [NSTask launchedTaskWithLaunchPath: @"/bin/sh"
	      arguments: [NSArray arrayWithObjects: @"-c",
				  [NSString stringWithFormat: handler, [theURL description]],
				  nil] ];

    }
  
  return YES;
}


//
//
//
- (void) update
{
  NSMutableAttributedString *aMutableAttributedString;
  int i;
  
  if ( ![self channel] )
    {
      return;
    }

#ifdef MACOSX
  // We empty the dock sub menu
  for (i = [dockSubMenu numberOfItems] - 1; i > -1; i--)
    {
      [dockSubMenu removeItem: [dockSubMenu itemAtIndex: i]];
    }
#endif
  
  aMutableAttributedString = [[NSMutableAttributedString alloc] init];
  
  for (i = 0; i < [[self channel] count]; i++)
    {
      NSDictionary *linkAttributes;
      Element *aElement;
      
      aElement = [[self channel] elementAtIndex: i];
      
      if ( [aElement type] == ITEM && [aElement link] )
	{
	  NSAttributedString *aAttributedString;
          
	  linkAttributes= [NSDictionary dictionaryWithObjectsAndKeys: [aElement link], NSLinkAttributeName,
#ifdef MACOSX
					[NSNumber numberWithInt: NSNoUnderlineStyle],
#else
					[NSNumber numberWithInt: GSNoUnderlineStyle],	
#endif
					NSUnderlineStyleAttributeName,
					[NSColor blackColor], NSForegroundColorAttributeName,
					NULL];
	  aAttributedString = [[NSAttributedString alloc] initWithString: [[aElement title] 
									    stringByAppendingString: @"\n"]
							  attributes: linkAttributes];
	  
	  [aMutableAttributedString appendAttributedString: aAttributedString];

#ifdef MACOSX
	  // We add a menu item in the dock sub menu
	  [dockSubMenu addItem: [self _constructMenuItem: [aElement title]
				      action: @selector(dockItemSelected:)
				      url: [aElement link]]];
#endif
      
	}
  }

#ifdef MACOSX
  // We complete the dock sub menu but a Refresh menu item
  [dockSubMenu addItem: [NSMenuItem separatorItem]];
  [dockSubMenu addItem: [self _constructMenuItem: @"Refresh"
			      action: @selector(dockItemUpdate:)
			      url: nil]];
#endif  

  [[textView textStorage] setAttributedString: aMutableAttributedString];
  RELEASE(aMutableAttributedString);

  // We set the count of plopview and ask to refresh it
  [[self plopView] setCount: [channel itemCount]];
  [[self plopView] setNeedsDisplay: YES];
}


@end


//
// private methods
//
@implementation PlopWindowController (Private)


#ifdef MACOSX
- (NSMenuItem *) _constructMenuItem: (NSString *) theTitle
                             action: (SEL) theSelector
                                url: (NSURL *) theURL
{
    NSMenuItem *item;

    // This is the "correct" way to create the menu items - this code is used if we're
    // running on a fixed system
    if (NSAppKitVersionNumber >= kFixedDockMenuAppKitVersion)
    {
        item = [[NSMenuItem alloc] initWithTitle: theTitle
                                          action: theSelector
                                   keyEquivalent: @""];
        AUTORELEASE(item);
        [item setTarget: self];
        [item setRepresentedObject: theURL];
        [item setEnabled: YES];
    }
    else // we're running on an OS version that isn't fixed; use NSInvocation
    {
        // This invocation is going to be of the form aSelector
        NSInvocation *myInv;

        myInv = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector: theSelector]];
        item = [[NSMenuItem alloc] initWithTitle: theTitle
                                          action: @selector(invoke)
                                   keyEquivalent: @""];
        AUTORELEASE(item);
        
        // This invocation is going to be an invocation of aSelector
        [myInv setSelector: theSelector];
        
        // This invocation is going to send its message to self
        [myInv setTarget: self];

        // The parameter to this invocation will be item, i.e. the NSMenuItem that should
        // be the sender to -menuSelected:  Note that we pass it at index 2 - indices 0 and 1
        // are taken by the hidden arguments self and _cmd, accessible through -setTarget:
        // and -setSelector:
        [myInv setArgument: &item atIndex: 2];

        // here we retain the invocation so it won't go away.  Later on we'll have to
        // release it to avoid leaking
        [item setTarget: RETAIN(myInv)];
        [item setTag: 1];

        [item setRepresentedObject: theURL];
        [item setEnabled: YES];
    }

    return item;
}
#endif


- (void) _updateWindowFrame
{
  if ( [[self channel] plop] )
    {
      NSRect theFrame;

      theFrame = [[self window] frame];
      [[[self channel] plop] setFrame: theFrame];
    }
}


@end
