//
//  TextViewHUD.m
//  Afficheur
//
//  Created by kichi on 08/04/16.
//  Copyright 2008 Katsuhiko Ichinose. All rights reserved.
//

#import "TextViewHUD.h"

@implementation TextViewHUD

- (id)initWithController:(id)controller;
{
	self = [super init];
	if (self)
	{
		_controller = controller;
		_items = [[NSMutableArray alloc] init];
		_properties = [[NSMutableDictionary alloc] init];
		[self setAllowsUndo:NO];
		[self setFieldEditor:YES];
		[self setInsertionPointColor:[NSColor whiteColor]];
	}
	return self;
}

- (void)dealloc
{
	[_items release];
	[_properties release];
	[super dealloc];
}

- (void)setupSelectedTextAttributes
{
	NSDictionary *attr = [self selectedTextAttributes];
	[self setSelectedTextAttributes:
	 [NSDictionary dictionaryWithObjectsAndKeys:
	  [NSColor grayColor], @"NSBackgroundColor",
	  [attr valueForKey:@"NSColor"], @"NSColor",
	  nil]];
}

#pragma mark NSResponder Delegates

- (void)keyDown:(NSEvent *)theEvent
{
	if ([theEvent keyCode] == 0x24)
	{
		if (_controller && [_controller respondsToSelector:@selector(enterKeyDown:)])
		{
			[_controller performSelector:@selector(enterKeyDown:)
								  withObject:[NSNumber numberWithInt:[theEvent modifierFlags]]];
		}
	}
	[super keyDown:theEvent];
}

- (void)keyUp:(NSEvent *)theEvent
{
	if ([theEvent keyCode] == 0x24)
	{
		if (_controller && [_controller respondsToSelector:@selector(enterKeyUp:)])
		{
			[_controller performSelector:@selector(enterKeyUp:)
							  withObject:[NSNumber numberWithInt:[theEvent modifierFlags]]];
		}
	}
	[super keyUp:theEvent];
}

#pragma mark NSTextView Delegates

- (void)setCompleteItem:(NSArray *)item
{
	//LOG(@"[%@ setCompleteItem]\n%@", [self className], item);
	if (item)
	{
		[_items release];
		_items = [[NSMutableArray alloc] initWithArray:item];
	}
}

- (void)setCompleteRange:(NSRange)range
{
	_range = range;
	if (range.length > 0)
	{
		unichar *characters = malloc(range.length * sizeof(unichar));
		if (characters)
		{
			@try
			{
				[[self string] getCharacters:characters range:range];
				//LOG(@"[%@ setCompleteRange]\n%@", [self className], [NSString stringWithCharacters:characters length:range.length]);
				[_properties setValue:[NSString stringWithCharacters:characters length:range.length]
							   forKey:@"completionSource"];
			}
			@catch (NSException *exception)
			{
				EXPLOG(@"[%@ setCompleteRange] EXCEPTION\n%@: %@", [self className], [exception name], [exception reason]);
			}
			@finally
			{
				free(characters);
			}
		}
	}
}

- (void)complete:(id)sender
{
	//LOG(@"[%@ complete]", [self className]);
	[self setSelectedRange:_range];// NSMakeRange(0, [[self string] length])];
	[super complete:sender];
	//LOG(@"[%@ complete] done", [self className]);
}

- (NSArray *)completionsForPartialWordRange:(NSRange)charRange
						indexOfSelectedItem:(int *)index
{
	//LOG(@"[%@ completionsForPartialWordRange]", [self className]);
	NSRange range = [self selectedRange];
	NSMutableArray *result = [NSMutableArray array];
	BOOL inseert = NO;
	if ([[_properties valueForKey:@"completionSource"] isEqualToString:@"!"])
	{
		[_items insertObject:@"!" atIndex:0];
		inseert = YES;
	}
	else if ([[_properties valueForKey:@"completionSource"] isEqualToString:@"#"])
	{
		[_items insertObject:@"#" atIndex:0];
		inseert = YES;
	}
	NSEnumerator *itemEnumerator = [_items objectEnumerator];
	id item;
	while ( (item = [itemEnumerator nextObject]) != nil ) {
		NSString *completionResult = item;
		NSRange sourceRange = [completionResult
							   rangeOfString:[_properties valueForKey:@"completionSource"]
							   options:NSCaseInsensitiveSearch];
		if ( sourceRange.location != NSNotFound ) {
			[result addObject:completionResult];
		}
	}
	[result sortUsingSelector:@selector(caseInsensitiveCompare:)];
	*index = 0;//[result indexOfObject:preferredResult];
	range = [self selectedRange];
	if ([result count] <= 0)
	{
		[self setSelectedRange:NSMakeRange(_range.location + _range.length, 0)];
	}
	if (inseert)
	{
		[_items removeObjectAtIndex:0];
	}
	//LOG(@"[%@ completionsForPartialWordRange] done %d", [self className], [result count]);
	return [NSArray arrayWithArray:result];
}

- (void)insertCompletion:(NSString *)word
	 forPartialWordRange:(NSRange)charRange
				movement:(int)movement
				 isFinal:(BOOL)flag
{
	//LOG(@"[%@ insertCompletion] %@", [self className], word);
	NSRange range = [self selectedRange];
	[super insertCompletion:word
		forPartialWordRange:charRange
				   movement:movement
					isFinal:flag];
	range = [self selectedRange];
	NSRange sourceRange = [word rangeOfString:[_properties valueForKey:@"completionSource"]
									  options:NSCaseInsensitiveSearch];
	if (sourceRange.location != NSNotFound)
	{
		int location = sourceRange.location + sourceRange.length;
		int length = [word length] - location;
		[self setSelectedRange:NSMakeRange(location + _range.location, length)];
	}
	else
	{
		[self setSelectedRange:NSMakeRange(_range.location + _range.length, 0)];
	}
	if (flag)
	{
		if (movement == NSLeftTextMovement)
		{
			int offset = 0;
			if ([self selectedRange].length == 0)
			{
				offset = 1;
			}
			[self setSelectedRange:NSMakeRange([self selectedRange].location - offset, 0)];
		}
		else if ( movement == NSRightTextMovement )
		{
			[self setSelectedRange:NSMakeRange([self selectedRange].location+[self selectedRange].length, 0)];
		}
		else if ( movement == NSReturnTextMovement && [self isFieldEditor] )
		{
			[[self delegate] sendAction:[[self delegate] action] to:[[self delegate] target]];
		}
		[_properties setValue:nil forKey:@"completionSource"];
	}
	//LOG(@"[%@ insertCompletion] done", [self className]);
}

- (NSRange)rangeForUserCompletion
{
	//LOG(@"[%@ rangeForUserCompletion]", [self className]);
	return _range;//NSMakeRange(0, [[self string] length]);
}

#pragma mark NSTextInput protocol

- (BOOL)hasMarkedText
{
	return [super hasMarkedText];
}

- (NSRange)markedRange
{
	return [super markedRange];
}

- (NSRange)selectedRange
{
	return [super selectedRange];
}

- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
{
	[super setMarkedText:aString selectedRange:selRange];
	if (_controller && [_controller respondsToSelector:@selector(adjustTextFieldSize)])
	{
		[_controller performSelector:@selector(adjustTextFieldSize)];
	}
}

- (void)unmarkText
{
	[super unmarkText];
	if (_controller && [_controller respondsToSelector:@selector(adjustTextFieldSize)])
	{
		[_controller performSelector:@selector(adjustTextFieldSize)];
	}
}

- (NSArray *)validAttributesForMarkedText
{
	return [super validAttributesForMarkedText];
}

- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
{
	NSAttributedString *result = [super attributedSubstringFromRange:theRange];
	if (_controller && [_controller respondsToSelector:@selector(adjustTextFieldSize)])
	{
		[_controller performSelector:@selector(adjustTextFieldSize)];
	}
	return result;
}

- (void)insertText:(id)aString
{
	[super insertText:aString];
	if (_controller && [_controller respondsToSelector:@selector(adjustTextFieldSize)])
	{
		[_controller performSelector:@selector(adjustTextFieldSize)];
	}
}

- (unsigned int)characterIndexForPoint:(NSPoint)thePoint
{
	return [super characterIndexForPoint:thePoint];
}

- (NSRect)firstRectForCharacterRange:(NSRange)theRange
{
	return [super firstRectForCharacterRange:theRange];
}

- (void)doCommandBySelector:(SEL)aSelector
{
	[super doCommandBySelector:aSelector];
	if (_controller && [_controller respondsToSelector:@selector(adjustTextFieldSize)])
	{
		[_controller performSelector:@selector(adjustTextFieldSize)];
	}
}

- (long)conversationIdentifier
{
	return [super conversationIdentifier];
}

@end
