//
//  MPT_AUView.m
//  AUCoderDemo
//
//  Created by Andrew Salamon on 5/17/06.
//  Copyright (c) 2006 Machine Perception Laboratory 
//  University of California San Diego.//

#import "MPT_AUView.h"


@interface MPT_Number : NSNumber
{
	BOOL hasValue;
}
+ (MPT_Number *)numberWithNoValue;

- (BOOL)hasValue;
- (void)setHasValue:(BOOL)value;
@end

@interface NSNumber(NoValue)
- (BOOL)hasValue;
@end


@implementation MPT_AUView
+ (NSRect)defaultFrame
{
	static NSRect defaultAUFrame = { 468, 531, 200, 65 };
	return defaultAUFrame;
}

- (id)init
{
	return [self initWithFrame:[[self class] defaultFrame]];
}

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
	{
        AU = 0;
		AUDisplayString = AUString = @"NA";
		
		[self setDefaultMin:-0.5];
		[self setDefaultMax:0.5];
		
		[self resetDynamicRange];
		
		count = 100;
		noValue = YES;
		values = [[NSMutableArray alloc] initWithCapacity:count];
		clearValues = NO;
    }
    return self;
}

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

- (BOOL)isFlipped
{
	return YES;
}

- (void)buildDisplayString
{
	if( AU != 0 )
	{
		[AUDisplayString release];
		AUDisplayString = [[NSString stringWithFormat:@"%@ %d", AUString, AU] retain];
	}
	else
	{
		[AUDisplayString release];
		AUDisplayString = [AUString copy];
	}
}

- (int)AU {
    return AU;
}

- (void)setAU:(int)value {
    if (AU != value)
	{
        AU = value;
		if( [AUString isEqualToString:@"NA"] )
		{
			[AUString release];
			AUString = [@"AU" retain];
		}
		[self buildDisplayString];
    }
}

- (NSString *)AUString
{
    return AUString;
}

- (void)setAUString:(NSString *)value
{
    if( AUString != value )
    {
        [AUString release];
        AUString = [value copy];
		[self buildDisplayString];
    }
}

- (float)defaultMin
{
    return defaultMin;
}

- (void)setDefaultMin:(float)value
{
    defaultMin = value;
}

- (float)defaultMax
{
    return defaultMax;
}

- (void)setDefaultMax:(float)value
{
    defaultMax = value;
}

- (float)min
{
    return min;
}

- (void)setMin:(float)value
{
    min = value;
}

- (float)max
{
    return max;
}

- (void)setMax:(float)value
{
    max = value;
}

- (void)resetDynamicRange
{
	clearValues = YES;
}

- (unsigned int)count
{
	return count;
}
- (void)setCount:(unsigned int)newCount
{
	count = newCount;
}

- (void)addValue:(float)value
{
	if( clearValues )
	{
		[self setMin:[self defaultMin]];
		[self setMax:[self defaultMax]];
		[values removeAllObjects];
		clearValues = NO;
	}

	if( [values count] > count )
	{
		[values removeObjectAtIndex:0];
		[values addObject:[NSNumber numberWithFloat:value]];
	}
	else
	{
		[values addObject:[NSNumber numberWithFloat:value]];
	}
	
	if( value < min )
		min = value;
	if( value > max )
		max = value;
	noValue = NO;
	[self setNeedsDisplay:YES];
}

- (void)addNoValue
{
	if( clearValues )
	{
		[self setMin:[self defaultMin]];
		[self setMax:[self defaultMax]];
		[values removeAllObjects];
		clearValues = NO;
	}

	if( [values count] > count )
	{
		[values removeObjectAtIndex:0];
		[values addObject:[MPT_Number numberWithNoValue]];
	}
	else
	{
		[values addObject:[MPT_Number numberWithNoValue]];
	}
	noValue = YES;
	[self setNeedsDisplay:YES];
}

- (BOOL)isEnabled
{
    return enabled;
}

- (void)setEnabled:(BOOL)value
{
    enabled = value;
}

- (void)clearValue
{
	noValue = YES;
	[self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect
{
	NSSize mySize = [self frame].size;
	float baseline = mySize.height - 18.0;
	NSRect aRect = NSMakeRect( 0.0, baseline, mySize.width, 1.0 );
	NSPoint center = NSMakePoint( 12.0, baseline );
	[[NSColor blackColor] setFill];
	NSRectFill( aRect );
	[AUDisplayString drawAtPoint:center withAttributes:nil];
	
	NSFrameRect( NSMakeRect( 0.0, 0.0, mySize.width, mySize.height ) );
	
	float inc = mySize.width / count;
	NSRect bar = NSMakeRect( 0.0, baseline, inc, mySize.height - baseline );
	float x = 0.0;
	float scale =  (mySize.height - 18.0) / (max - min);
	NSEnumerator *valueEnum = [values objectEnumerator];
	NSNumber *value;
	while( value = [valueEnum nextObject] )
	{
		if( [value hasValue] )
		{
			bar.size.height = ([value floatValue] - min) * scale;
			bar.origin.x = x;
			bar.origin.y = baseline - bar.size.height;
			NSRectFill( bar );
		}
		x += inc;
	}
	
	if( [values count] && !noValue )
	{
		NSString *cur = [NSString stringWithFormat:@"%.4f", [[values lastObject] floatValue]];
		center.x = mySize.width - 50.0;
		[cur drawAtPoint:center withAttributes:nil];
	}
}

@end


@implementation MPT_Number
+ (MPT_Number *)numberWithNoValue
{
	MPT_Number *tmp = [[MPT_Number alloc] init];
	[tmp setHasValue:NO];
	return [tmp autorelease];
}

- (id)init
{
	if( self = [super init] )
	{
		[self setHasValue:YES];
	}
	return self;
}

- (BOOL)hasValue
{
    return hasValue;
}

- (void)setHasValue:(BOOL)value
{
	hasValue = value;
}
@end

@implementation NSNumber(NoValue)
- (BOOL)hasValue
{
	return YES;
}
@end