//
//  DraggedArrayController.m
//  Afficheur
//
//  Created by kichi on 09/03/05.
//  Copyright 2009 Katsuhiko Ichinose. All rights reserved.
//

#import "DraggedArrayController.h"


@implementation DraggedArrayController

- (id)init
{
	self = [super init];
	if (self)
	{
		_tableView = nil;
	}
	return self;
}

- (void)setTableView:(NSTableView *)tableView
{
	_tableView = tableView;
}

- (BOOL)tableView:(NSTableView *)aTableView
writeRowsWithIndexes:(NSIndexSet *)rowIndexes
	 toPasteboard:(NSPasteboard *)pboard
{
	BOOL result = NO;
	@try
	{
		//LOG(@"[%@ writeRowsWithIndexes]\n%@\n%@\n%@", [self className], aTableView, rowIndexes, pboard);
		if (!_tableView || ([rowIndexes count] <= 0))
		{
			return NO;
		}
		//LOG(@"[%@ writeRowsWithIndexes] count: %d", [self className], [rowIndexes count]);
		//LOG(@"[%@ writeRowsWithIndexes] first: %d", [self className], [rowIndexes firstIndex]);
		int count = [rowIndexes count];
		unsigned int *indexes = malloc(count * sizeof(unsigned int));
		if (indexes)
		{
			unsigned int *p = indexes;
			int size = [rowIndexes getIndexes:indexes maxCount:count inIndexRange:NULL];
			//LOG(@"[%@ writeRowsWithIndexes] getIndexes\n%d, %d", [self className], size, *p);
			@try
			{
				NSMutableString *string = [NSMutableString stringWithFormat:@"%d", *p];
				int i = 1;
				while (i < size)
				{
					p++;
					//LOG(@"[%@ writeRowsWithIndexes] %d, %d", [self className], i, *p);
					[string appendString:[NSString stringWithFormat:@" %d", *p]];
					i++;
				}
				//LOG(@"[%@ writeRowsWithIndexes] string\n%@", [self className], string);
				[pboard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner:self];
				[pboard setString:string forType:NSStringPboardType];
				result = YES;
			}
			@catch (NSException *exception)
			{
				EXPLOG(@"[%@ writeRowsWithIndexes] EXCEPTION\n%@: %@", [self className], [exception name], [exception reason]);
			}
			@finally
			{
				free(indexes);
			}
		}
	}
	@catch (NSException *exception)
	{
		EXPLOG(@"[%@ writeRowsWithIndexes] EXCEPTION\n%@: %@", [self className], [exception name], [exception reason]);
	}
	return result;
}

- (NSDragOperation)tableView:(NSTableView *)aTableView
				validateDrop:(id < NSDraggingInfo >)info
				 proposedRow:(int)row
	   proposedDropOperation:(NSTableViewDropOperation)operation
{
	NSDragOperation result = NSDragOperationNone;
	@try
	{
		//LOG(@"[%@ validateDrop]\n%@\n%@\n%d, %d", [self className], aTableView, info, row, operation);
		id source = [info draggingSource];
		//LOG(@"[%@ validateDrop] source\n%@\n%p\n%p", [self className], source, _tableView, self);
		if (!_tableView || !source || [source isEqual:_tableView])
		{
			//LOG(@"[%@ validateDrop] self\n%@", [self className], [source dataSource]);
			return NSDragOperationNone;
		}
		if (operation != NSTableViewDropAbove)
		{
			//LOG(@"[%@ validateDrop] != NSTableViewDropAbove", [self className]);
			return NSDragOperationNone;
		}
		NSPasteboard *pboard = [info draggingPasteboard];
		NSString *string = [pboard stringForType:NSStringPboardType];
		if (!string)
		{
			return NSDragOperationNone;
		}
		result = NSDragOperationMove;
	}
	@catch (NSException *exception)
	{
		EXPLOG(@"[%@ validateDrop] EXCEPTION\n%@: %@", [self className], [exception name], [exception reason]);
	}
	return result;
}

- (BOOL)tableView:(NSTableView *)aTableView
	   acceptDrop:(id < NSDraggingInfo >)info
			  row:(int)row
	dropOperation:(NSTableViewDropOperation)operation
{
	BOOL result = NO;
	@try
	{
		//LOG(@"[%@ acceptDrop]\n%@\n%@\n%d, %d", [self className], aTableView, info, row, operation);
		id source = [info draggingSource];
		//LOG(@"[%@ validateDrop] source\n%@\n%p\n%p", [self className], source, _tableView, self);
		if (!_tableView || !source || [source isEqual:_tableView])
		{
			//LOG(@"[%@ acceptDrop] self", [self className]);
			return NO;
		}
		if (operation != NSTableViewDropAbove)
		{
			//LOG(@"[%@ acceptDrop] != NSTableViewDropAbove", [self className]);
			return NO;
		}
		NSPasteboard *pboard = [info draggingPasteboard];
		//LOG(@"[%@ acceptDrop] pboard\n%@", [self className], pboard);
		//LOG(@"[%@ acceptDrop] string\n%@", [self className], [pboard stringForType:NSStringPboardType]);
		NSString *string = [pboard stringForType:NSStringPboardType];
		if (!string)
		{
			return NO;
		}
		NSMutableArray *items = [NSMutableArray array];
		NSArray *indexes = [string componentsSeparatedByString:@" "];
		NSEnumerator *enumerator = [indexes objectEnumerator];
		id obj;
		while ((obj = [enumerator nextObject]))
		{
			int index = [obj intValue];
			id item = [[[source dataSource] arrangedObjects] objectAtIndex:index];
			if (!item)
			{
				return NO;
			}
			[items addObject:[NSDictionary dictionaryWithObjectsAndKeys:
							  item, @"item",
							  [NSNumber numberWithInt:index], @"index",
							  nil]];
		}
		//LOG(@"[%@ acceptDrop] item\n%@", [self className], item);
		NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet];
		int at = row;
		enumerator = [items objectEnumerator];
		while ((obj = [enumerator nextObject]))
		{
			int index = [[obj valueForKey:@"index"] intValue];
			id item = [obj valueForKey:@"item"];
			if (item)
			{
				//LOG(@"[%@ acceptDrop] %d, %d", [self className], index, at);
				[self insertObject:item atArrangedObjectIndex:at];
				[indexSet addIndex:index];
				at++;
			}
		}
		[[source dataSource] removeObjectsAtArrangedObjectIndexes:indexSet];
		result = YES;
	}
	@catch (NSException *exception)
	{
		EXPLOG(@"[%@ acceptDrop] EXCEPTION\n%@: %@", [self className], [exception name], [exception reason]);
	}
	return result;
}


#pragma mark NSTableDataSource Protocols

- (int)numberOfRowsInTableView:(NSTableView *)aTableView
{
	return 0;
}

- (id)_Z_tableView:(NSTableView *)aTableView
objectValueForTableColumn:(NSTableColumn *)aTableColumn
			row:(int)rowIndex
{
	return nil;
}

@end
