/*
**  PreferencesPanelController.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 "PreferencesPanelController.h"

#import "ConfigureWindowController.h"
#import "Constants.h"
#import "ExtendedTableColumn.h"
#import "NSStringExtensions.h"
#import "Plop.h"
#import "PlopFolio.h"
#import "PreferencesPanel.h"

// XML Headers needed under GNUstep
#ifndef MACOSX
#import <Foundation/GSXML.h>

// XML Headers needed under Cocoa
#else
#import <CoreServices/CoreServices.h>
#endif


@implementation PreferencesPanelController

//
//
//
- (id) initWithWindowNibName: (NSString *) theNibName
{
#ifdef MACOSX
  self = [super initWithWindowNibName: theNibName];
#else
  PreferencesPanel *thePanel;
  
  thePanel = [[PreferencesPanel alloc] initWithContentRect:NSMakeRect(100,100,355,275)
				       styleMask: (NSClosableWindowMask|NSResizableWindowMask)
				       backing: NSBackingStoreBuffered
				       defer: NO];

  self = [super initWithWindow: thePanel];
  
  [thePanel layoutPanel];
  [thePanel setDelegate: self];

  // We link our outlets
  tableView = [thePanel tableView];
  browserPopUpButton = [thePanel browserPopUpButton];
  browserField = [thePanel browserField];

  RELEASE(thePanel);
#endif

  // We set our title
  [[self window] setTitle: _(@"Preferences...")];

  // We set our custom table column on OS X
#ifdef MACOSX
  {
    ExtendedTableColumn *extendedTableColumn;
    ExtendedButtonCell *cell;
    
    cell = [[ExtendedButtonCell alloc] init];
    
    [cell setButtonType: NSSwitchButton];
    [cell setImagePosition: NSImageOnly];
    [cell setControlSize: NSSmallControlSize];
    
    extendedTableColumn = (ExtendedTableColumn *)[tableView tableColumnWithIdentifier: @"active"];
    
    [extendedTableColumn setDataCell: cell];
    [extendedTableColumn setShouldUseMouse: YES];
    [extendedTableColumn setShouldUseAndSetState: YES];
    
    RELEASE(cell);
  }
#endif
  
  // We get our defaults for this panel
  [self initializeFromDefaults];

  return self;
}


//
//
//
- (void) dealloc
{
  [super dealloc];
}


//
//
//
- (void) initializeFromDefaults
{
  int index;
  
  index = [[NSUserDefaults standardUserDefaults] integerForKey: @"BROWSER_SOURCE"];
  
  [browserPopUpButton selectItemAtIndex: index];
  [browserPopUpButton synchronizeTitleAndSelectedItem];

  if ( index > 0 )
    {
      [browserField setEditable: YES];
    }
  else
    {
      [browserField setEditable: NO];
    }

  if ( [[NSUserDefaults standardUserDefaults] objectForKey: @"BROWSER_PATH"] )
    {
      [browserField setStringValue: [[NSUserDefaults standardUserDefaults] 
				      objectForKey: @"BROWSER_PATH"] ];
    }      
}

//
// datasource methods
//
- (id)           tableView: (NSTableView *) aTableView
 objectValueForTableColumn: (NSTableColumn *) aTableColumn
                       row: (int) rowIndex
{
  Plop *aPlop;

  aPlop = [[(PlopFolio *)[NSApp delegate] allPlops] objectAtIndex: rowIndex];

  if ( [[[aTableColumn headerCell] stringValue] isEqual: _(@"Name")] )
    {
      return [aPlop title];
    }
  else
    {
      return ( [aPlop isActive] ? _(@"Yes") : _(@"No") );
    }
}


//
//
//
- (int) numberOfRowsInTableView: (NSTableView *) aTableView
{
  return [[(PlopFolio *)[NSApp delegate] allPlops] count];
}


//
//
//
- (int)    tableView: (NSTableView *) aTableView
 stateForTableColumn: (NSTableColumn *) aTableColumn 
		 row: (int) rowIndex
{
  Plop *aPlop;
  
  aPlop = [[(PlopFolio *)[NSApp delegate] allPlops] objectAtIndex: rowIndex];

  return ( [aPlop isActive] ? NSOnState : NSOffState );
}


//
//
//
- (void) tableView: (NSTableView *) aTableView
	  setState: (int) aState
    forTableColumn: (NSTableColumn *) aTableColumn 
	       row: (int) rowIndex
{
  Plop *aPlop;
  
  aPlop = [[(PlopFolio *)[NSApp delegate] allPlops] objectAtIndex: rowIndex];

  if (aState == NSOnState)
    {
      [aPlop setActive: YES];
    }
  else if (aState == NSOffState)
    {
      [aPlop setActive: NO];
    }
}


//
// delegate methods
//
- (void) windowWillClose: (id) sender
{
  NSLog(@"Closing the Preferences Panel.");
  
  // We save our userdefaults
  [browserPopUpButton synchronizeTitleAndSelectedItem];  
  [[NSUserDefaults standardUserDefaults] setInteger: [browserPopUpButton indexOfSelectedItem]
					 forKey: @"BROWSER_SOURCE"];
  [[NSUserDefaults standardUserDefaults] setObject: [browserField stringValue]
					 forKey: @"BROWSER_PATH"];
  [[NSUserDefaults standardUserDefaults] synchronize];

  // We synchronize our plops
  [(PlopFolio *)[NSApp delegate] synchronize];
  [(PlopFolio *)[NSApp delegate] showAllPlops];
}


//
// action methods
//
- (IBAction) configureClicked: (id) sender
{
  ConfigureWindowController *aConfigureWindowController;
  int index;

  index = [tableView selectedRow];

  if ( index < 0 )
    {
      NSBeep();
      return;
    }

  aConfigureWindowController = [[ConfigureWindowController alloc] initWithWindowNibName: @"ConfigureWindow"];
  [aConfigureWindowController setPlop: [[(PlopFolio *)[NSApp delegate] allPlops] objectAtIndex: index]];

  [[aConfigureWindowController window] orderFront: nil];
}

- (IBAction) deleteClicked: (id) sender
{
  int choice, index;

  index = [tableView selectedRow];
  
  if ( index < 0 )
    {
      NSBeep();
      return;
    }

  choice = NSRunAlertPanel(_(@"Delete..."),
			   _(@"Are you sure you want to delete this Plop?"),
			   _(@"Cancel"), // default
			   _(@"Yes"),    // alternate
			   NULL);
  
  // If we must delete it...
  if ( choice == NSAlertAlternateReturn )
    {
      Plop *aPlop;
      
      aPlop = [[(PlopFolio *)[NSApp delegate] allPlops] objectAtIndex: index];

      // We remove the icon of the plop
      [[NSFileManager defaultManager] removeFileAtPath: [NSString stringWithFormat: @"%@/%@", 
								  PlopFolioUserLibraryPath(),
								  [aPlop iconName]]
				      handler: nil];
      

      // We remove the plop
      [[(PlopFolio *)[NSApp delegate] allPlops] removeObjectAtIndex: index];
      [tableView reloadData];
    }
}


//
//
//
- (IBAction) importClicked: (id) sender
{
  NSOpenPanel *oPanel;
  int result;
  
  oPanel = [NSOpenPanel openPanel];
  [oPanel setAllowsMultipleSelection:NO];
  result = [oPanel runModalForDirectory: NSHomeDirectory() 
		   file: nil
		   types: nil];
  
  if ( result == NSOKButton )
    {
      NSArray *fileToOpen;
      int count;
      
      fileToOpen = [oPanel filenames];
      count = [fileToOpen count];
      
      if ( count > 0 )
	{
	  [self _importKlipUsingPath: [fileToOpen objectAtIndex: 0]];
	}
    }
}


//
//
//
- (IBAction) selectionInBrowserPopUpButtonHasChanged: (id) sender
{
  [browserPopUpButton synchronizeTitleAndSelectedItem];

  if ( [browserPopUpButton indexOfSelectedItem] == 0 )
    {
      [browserField setEditable: NO];
    }
  else
    {
      [browserField setEditable: YES];
    }
}

@end



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

- (void) _importKlipUsingPath: (NSString *) thePath
{
  // GNUstep XML Parsing Code
#ifndef MACOSX
  GSXMLParser *aParser;
  NSData *aData;


  aData = [NSData dataWithContentsOfFile: thePath];
  aParser = [GSXMLParser parserWithData: aData];
  [aParser keepBlanks: NO];
  
  if ( [aParser parse] )
    {
      GSXMLDocument *aDocument;
      GSXMLNode *aRoot, *aNode;
      Plop *aPlop;

      aDocument = [aParser document];
  
      aRoot = [aDocument root];
      
      if ( [[aRoot name] caseInsensitiveCompare: @"KLIP"] != NSOrderedSame )
	{
	  NSLog(@"Not a Klip. Ignoring.");
	  return;
	}
      
      aNode = [aRoot firstChildElement];
      
      // We initialize our plop
      aPlop = [[Plop alloc] init];

      //
      // We loop inside our owner/identity/locations/setup/script nodes
      //
      while (aNode != nil)
	{ 
	  [self _parseKlipInformationsFromNode: aNode
		plop: aPlop];
	  
	  // We get the next node
	  aNode = [aNode nextElement];
	}

      // We add our plop to our list of active plops
      [aPlop cache];

      [[(PlopFolio *)[NSApp delegate] allPlops] addObject: aPlop];
      [(PlopFolio *)[NSApp delegate] synchronize];
      
      RELEASE(aPlop);
    }
  else
    {
      NSLog(@"error occured while parsing .klip");
    }

  // Cocoa XML Parsing Code
#else
  CFXMLTreeRef aTreeRef, xmlTreeRoot;
  CFXMLNodeRef xmlRoot;
  NSData *aData;
  int i;
  
  aData = [NSData dataWithContentsOfFile: thePath];
  aTreeRef = CFXMLTreeCreateFromData(kCFAllocatorDefault,
				     (CFDataRef)aData,
				     NULL,
				     kCFXMLParserSkipWhitespace|kCFXMLParserSkipMetaData,
				     kCFXMLNodeCurrentVersion);
  if ( !aTreeRef )
    {
      NSRunAlertPanel(_(@"Error!"),
                      _(@"Corrupted XML. Ignoring Klip."),
                      _(@"OK"),
                      NULL,
                      NULL);
      return;
    }
  
  for (i = 0; i < CFTreeGetChildCount(aTreeRef); i++)
    {
      xmlTreeRoot = CFTreeGetChildAtIndex(aTreeRef, i);
      xmlRoot = CFXMLTreeGetNode(xmlTreeRoot);
      
      if ( [(NSString*)CFXMLNodeGetString(xmlRoot) caseInsensitiveCompare: @"KLIP"] == NSOrderedSame )
	{
	  // We found a klip!
	  CFXMLTreeRef xmlSubTreeRef;
	  CFXMLNodeRef aNode;
	  int j;
	  
	  Plop *aPlop;
	  
	  // We initialize our plop
	  aPlop = [[Plop alloc] init];
	  
	  for (j = 0; j < CFTreeGetChildCount(xmlTreeRoot); j++)
	    {
	      xmlSubTreeRef = CFTreeGetChildAtIndex(xmlTreeRoot, j);
	      aNode = CFXMLTreeGetNode(xmlSubTreeRef);
	      
	      if ( CFXMLNodeGetTypeCode(aNode) == kCFXMLNodeTypeElement )
		{
		  [self _parseKlipInformationsFromNode: (id)xmlSubTreeRef
			plop: aPlop];
		}
	    }
	  
	  // We add our plop to our list of active plops
	  [aPlop cache];
	  
	  [[(PlopFolio *)[NSApp delegate] allPlops] addObject: aPlop];
	  [(PlopFolio *)[NSApp delegate] synchronize];
	  
	  RELEASE(aPlop);
	}
    }
#endif
  
  [tableView reloadData];
}


//
//
//
- (void) _updatePlop: (Plop *) thePlop
		name: (NSString *) theName
	     content: (NSString *) theContent
{
  if ( [theName caseInsensitiveCompare: @"TITLE"] == NSOrderedSame )
    {
      [thePlop setTitle: theContent];
    }
  else if ( [theName caseInsensitiveCompare: @"ICON"] == NSOrderedSame )
    {
      [thePlop setIconSource: [NSURL URLWithString: theContent]];
    }
  else if ( [theName caseInsensitiveCompare: @"BANNER"] == NSOrderedSame )
    {
      [thePlop setBannerSource: [NSURL URLWithString: theContent] ];
    }
  else if ( [theName caseInsensitiveCompare: @"CONTENTSOURCE"] == NSOrderedSame )
    {
      [thePlop setContentSource: [NSURL URLWithString: theContent] ];
    }
  else if ( [theName caseInsensitiveCompare: @"DEFAULTLINK"] == NSOrderedSame )
    {
      [thePlop setDefaultLink: [NSURL URLWithString: theContent] ];
    }
  else if ( [theName caseInsensitiveCompare: @"DESCRIPTION"] == NSOrderedSame )
    {
      [thePlop setDescription: theContent];
    }
  else if ( [theName caseInsensitiveCompare: @"REFRESH"] == NSOrderedSame )
    {
      [thePlop setRefresh: [theContent intValue] ];
    }
  else if ( [theName caseInsensitiveCompare: @"VERSION"] == NSOrderedSame )
    {
      [thePlop setPlopVersion: theContent];
    }
}


//
// 
//
- (void) _parseKlipInformationsFromNode: (id) theNode
				   plop: (Plop *) thePlop
{
  // 
  // GNUstep XML Parsing Code
  // 
#ifndef MACOSX
  GSXMLNode *aChild;
  static int	textNodeType = -1;

  if (textNodeType < 0)
    {
      textNodeType = [GSXMLNode typeFromDescription: @"XML_TEXT_NODE"];
    }
  
  // We loop inside our channel/image/item node attributes
  if ( (aChild = [theNode firstChildElement]) )
    {
      while ( aChild )
	{
	  NSString *aName, *aContent;
	  GSXMLNode *aNode;

	  aNode = [aChild firstChild];
	  
	  while ( aNode )
	    {
	      if ( [aNode type] == textNodeType )
		{
		  if ( [[[aNode content] stringByTrimmingWhiteSpaces] length] > 0 )
		    {
		      break;
		    }
		}
	     
	      aNode = [aNode next];
	    }
     
	  if ( !aNode )
	    {
	      aChild = [aChild next];
	      continue;
	    }

	  aName = [aChild name];
	  aContent = [[aNode content] stringByTrimmingWhiteSpaces];

	  if (aName && aContent)
	    {
	      [self _updatePlop: thePlop
		    name: aName
		    content: aContent];
	    }
	      
	  aChild = [aChild nextElement];
	}
    }
  else
    {
      NSLog(@"No children");
    }
#else
  int i;
  
  for (i = 0; i < CFTreeGetChildCount((CFXMLTreeRef)theNode); i++)
    {
      CFXMLTreeRef xmlTreeRef;
      CFXMLNodeRef xmlNode;
      
      xmlTreeRef = CFTreeGetChildAtIndex((CFXMLTreeRef)theNode, i);
      xmlNode = CFXMLTreeGetNode(xmlTreeRef);
      
      if ( CFXMLNodeGetTypeCode(xmlNode) == kCFXMLNodeTypeElement )
        {
	  NSString *aName, *aContent;

          CFXMLTreeRef xmlSubTreeRef;
          CFXMLNodeRef xmlSubNode;
	  int j;

	  xmlSubTreeRef = NULL;
	  xmlSubNode = NULL;

	  for ( j = 0; j < CFTreeGetChildCount(xmlTreeRef); j++ )
	    {
	      xmlSubTreeRef = CFTreeGetChildAtIndex(xmlTreeRef, j);
	      xmlSubNode = CFXMLTreeGetNode(xmlSubTreeRef);

	      if ( CFXMLNodeGetTypeCode(xmlNode) == kCFXMLNodeTypeElement )
		{
		  break;
		}
	      else
		{
		  xmlSubNode = NULL;
		}
	    }
          
          if ( !xmlSubNode )
            {
              continue;
            }
          
          aName = (NSString *)CFXMLNodeGetString(xmlNode);
          aContent = [(NSString *)CFXMLNodeGetString(xmlSubNode) stringByTrimmingWhiteSpaces];
          
	  if (aName && aContent)
	    {
	      [self _updatePlop: thePlop
		    name: aName
		    content: aContent];
	    }
        }
    }
  
#endif
}

@end


//
// Custom NSButton cell
//
@implementation ExtendedButtonCell


@end
