//
//  BCSeriesTableController.m
//  BioCocoa
//
//  Created by Scott Christley on 10/07/08.
//  Copyright (c) 2003-2009 The BioCocoa Project.
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//  notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//  notice, this list of conditions and the following disclaimer in the
//  documentation and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//  derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#import "BCSeriesTableController.h"
#import "BCSeries.h"
#import "BCGEODownloadController.h"

#import <ApplicationServices/ApplicationServices.h>

@implementation BCSeriesTableController

// Use
- init
{
  return [self initWithSeries: [BCSeries getAllSeries]];
}

// Default constructor
- initWithSeries: (NSDictionary *)aSet
{
  self = [super init];
  if (self) {
    series = [[NSMutableDictionary dictionaryWithDictionary: aSet] retain];
    dataset = [[NSMutableArray arrayWithArray: [series allKeys]] retain];
    printf("%s\n", [[dataset description] UTF8String]);
    datasetSearch = nil;
    
    [NSBundle loadNibNamed: @"BCSeriesTable" owner: self];
  }
  return self;
}

- (void)dealloc
{
  if (series) [series release];
  [super dealloc];
}

- (void)awakeFromNib
{
  [datasetTable registerForDraggedTypes: [NSArray arrayWithObject:BCSeriesDataType] ];

	// update the table view
	datasetSearch = nil;
	[datasetTable setDataSource: self];
} 

- (void)makeKeyAndOrderFront: (id)sender
{
	[datasetWindow makeKeyAndOrderFront: sender];
}

//
// Manage the user interface
//
- (void)updateColumnButton
{
  NSSet *keys = [BCSeries keysForSeries: [series allValues] withInternalKeys: NO];
  NSArray *a = [keys allObjects];
  NSMutableArray *addList = [NSMutableArray arrayWithArray: a];
  NSMutableArray *delList = [NSMutableArray arrayWithArray: a];
  NSArray *tc = [datasetTable tableColumns];

  int i;
  for (i = 0; i < [tc count]; ++i) {
    NSTableColumn *c = [tc objectAtIndex: i];
    [addList removeObject: [c identifier]];
  }
  [delList removeObjectsInArray: addList];

  [datasetColumns removeAllItems];
  [datasetColumns addItemWithTitle: @"Modify Columns"];
  for (i = 0; i < [addList count]; ++i) {
    NSString *s = [NSString stringWithFormat: @"Add - %@", [addList objectAtIndex: i]];
    [datasetColumns addItemWithTitle: s];
  }
  for (i = 0; i < [delList count]; ++i) {
    NSString *s = [NSString stringWithFormat: @"Remove - %@", [delList objectAtIndex: i]];
    [datasetColumns addItemWithTitle: s];
  }
  [datasetColumns selectItemAtIndex: 0];
}

- (IBAction)loadSeries: (id)sender
{
  int i = [datasetTable selectedRow];
  if (i == -1) return;
  else {
    id theRecord;
    if (datasetSearch) theRecord = [datasetSearch objectAtIndex: i];
    else theRecord = [dataset objectAtIndex: i];
    theRecord = [series objectForKey: theRecord];
    [theRecord loadIfNecessary];
    [datasetTable reloadData];
    [self updateColumnButton];
  }
}

- (IBAction)showPlatforms: (id)sender
{
  int i = [datasetTable numberOfSelectedRows];
  if (i == 0) return;

  BOOL requiresLoad = NO;
  if (i == 1) {
    id theRecord;
    if (datasetSearch) theRecord = [datasetSearch objectAtIndex: i];
    else theRecord = [dataset objectAtIndex: i];
    theRecord = [series objectForKey: theRecord];
    if (![theRecord isLoaded]) requiresLoad = YES;
  } else {
    
  }
}

- (IBAction)showSamples: (id)sender
{
}

- (IBAction)showProbes: (id)sender
{
}

- (IBAction)showGEODownload: (id)sender
{
  id geoDownload = [BCGEODownloadController sharedGEODownload];
  [geoDownload makeKeyAndOrderFront: sender];
}

- (IBAction)modifyTableColumn: (id)sender
{
  NSString *s = [sender titleOfSelectedItem];
  if ([s isEqualToString: @"Modify Columns"]) return;
  
  NSRange r1, r2;
  r1 = [s rangeOfString: @"Add - "];
  if (r1.location != NSNotFound) {
    r2.location = r1.length;
    r2.length = [s length] - r2.location;
    NSString *anId = [s substringWithRange: r2];
    NSTableColumn *tc = [[[NSTableColumn alloc] initWithIdentifier: anId] autorelease];
    [tc setEditable: NO];
    [[tc headerCell] setStringValue: anId];
    [datasetTable addTableColumn: tc];
    [self updateColumnButton];
    return;
  }
  
  r1 = [s rangeOfString: @"Remove - "];
  if (r1.location != NSNotFound) {
    r2.location = r1.length;
    r2.length = [s length] - r2.location;
    NSString *anId = [s substringWithRange: r2];
    [datasetTable removeTableColumn: [datasetTable tableColumnWithIdentifier: anId]];
    [self updateColumnButton];
    return;
  }
}

//
// Search
//
- (IBAction)searchSeries: (id)sender
{
	NSString *s = [sender stringValue];
	//printf("search %d %s\n", [s length], [s UTF8String]);

	if (datasetSearch) [datasetSearch release];
	datasetSearch = nil;
	if ([s length] == 0) {
		[datasetTable reloadData];
		return;
	}

	int i, j;
  NSArray *tc = [datasetTable tableColumns];
  NSMutableArray *searchFields = [NSMutableArray new];
  for (i = 0; i < [tc count]; ++i) {
    NSTableColumn *c = [tc objectAtIndex: i];
    [searchFields addObject: [c identifier]];
  }

	datasetSearch = [NSMutableArray new];
	for (i = 0; i < [dataset count]; ++i) {
    id theRecordId = [dataset objectAtIndex:i];
    id theRecord = [series objectForKey: theRecordId];
    for (j = 0; j < [searchFields count]; ++j) {
      NSString *anId = [searchFields objectAtIndex: j];
      NSRange r = [[theRecord valueForKey: anId] rangeOfString: s options: NSCaseInsensitiveSearch];
      if (r.location != NSNotFound) {
        [datasetSearch addObject: theRecordId];
        break;
      }
    }
	}
	[datasetTable reloadData];
}

//
// Inspector panel
//
- (void)updateInspectorText
{
  int i = [datasetTable selectedRow];
  if (i == -1) {
    //[inspectorText setString: @""];
  } else {
		id theRecord;
    if (datasetSearch) theRecord = [datasetSearch objectAtIndex:i];
    else theRecord = [dataset objectAtIndex:i];
    theRecord = [series objectForKey: theRecord];
    //[inspectorText setString: [theRecord seriesDescription]];
    [[inspectorText mainFrame] loadHTMLString: [theRecord seriesHTMLDescription] baseURL: nil];
  }
}

- (void)showInspector: (id)sender
{
  [self updateInspectorText];
  [inspectorPanel makeKeyAndOrderFront: sender];
}

//
// Manage the table of series
//
- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
	if (datasetSearch)
		return [datasetSearch count];
	else
		return [dataset count];
}

- (id)tableView:(NSTableView *)aTableView
    objectValueForTableColumn:(NSTableColumn *)aTableColumn
            row:(int)rowIndex
{
  id theRecord, theValue;
  
	printf("tableView:objectValueForTableColumn:row:\n");
	if (datasetSearch) {
		NSParameterAssert(rowIndex >= 0 && rowIndex < [datasetSearch count]);
		theRecord = [datasetSearch objectAtIndex:rowIndex];
    theRecord = [series objectForKey: theRecord];
		theValue = [theRecord valueForKey:[aTableColumn identifier]];    
		return theValue;
	} else {
		NSParameterAssert(rowIndex >= 0 && rowIndex < [dataset count]);
		theRecord = [dataset objectAtIndex:rowIndex];
    theRecord = [series objectForKey: theRecord];
		theValue = [theRecord valueForKey:[aTableColumn identifier]];    
		return theValue;
	}
}

- (void)tableView:(NSTableView *)aTableView
   setObjectValue:anObject
   forTableColumn:(NSTableColumn *)aTableColumn
              row:(int)rowIndex
{
#if 0
  id theRecord;
  
	printf("tableView:setObjectValue:forTableColumn:row:\n");
	if (datasetSearch) {
		NSParameterAssert(rowIndex >= 0 && rowIndex < [datasetSearch count]);
		theRecord = [datasetSearch objectAtIndex:rowIndex];
		[theRecord setObject:anObject forKey:[aTableColumn identifier]];
	} else {
		NSParameterAssert(rowIndex >= 0 && rowIndex < [dataset count]);
		theRecord = [dataset objectAtIndex:rowIndex];
		[theRecord setObject:anObject forKey:[aTableColumn identifier]];
	}
#endif
  return;
}

//
// NSTableView delegate methods
//
- (void)tableViewSelectionDidChange:(id)sender
{
	printf("tableViewSelectionDidChange:\n");
  [self updateColumnButton];
  [self updateInspectorText];
}

//
// Drag/Drop support
//
- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard 
{
  // Copy the series id to the pasteboard.
  unsigned int i = [rowIndexes firstIndex];
  id theRecord;
  if (datasetSearch) theRecord = [datasetSearch objectAtIndex:i];
  else theRecord = [dataset objectAtIndex:i];
  theRecord = [series objectForKey: theRecord];
  NSString *s = [theRecord getId];
    
  [pboard declareTypes:[NSArray arrayWithObject:BCSeriesDataType] owner:self];
  [pboard setString:s forType:BCSeriesDataType];

  return YES;
}

//
//
//
- (void)webView:(WebView *)sender decidePolicyForNavigationAction:(NSDictionary *)actionInformation
        request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id)listener {

  //printf("webView:decidePolicyForNavigationAction:request:frame:\n");

  NSURL *anURL = [request URL];
  NSString *aString = [anURL absoluteString];
  //printf("%s\n", [aString UTF8String]);
  if ([aString isEqualToString: @"about:blank"]) {
    [listener use];
  } else {
    NSRange r = [aString rangeOfString: @"applewebdata:"];
    if (r.location != NSNotFound) {
      [listener use];
    } else {
      [listener ignore];
      LSOpenCFURLRef((CFURLRef)anURL, NULL);
    }
  }
}

@end
