//
//  MPT_Face.m
//  AUCoderDemo
//
//  Created by Andrew Salamon on 6/29/06.
//  Copyright (c) 2006 Machine Perception Laboratory. University of California San Diego.
//  All rights reserved.

#import "MPT_Face.h"


@implementation MPT_Face
- (id)initWithFace:(NSRect)_face
{
	if( self = [super init] )
	{
		[self setFace:_face];
		[self setFeatures:[NSMutableArray array]];		
	}
	return self;
}

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

- (id)copyWithZone:(NSZone *)zone
{
	MPT_Face *cp = [[MPT_Face alloc] initWithFace:[self face]];

	NSMutableArray *tmpPoints = [NSMutableArray array];
	NSEnumerator *pointEnum = [points objectEnumerator];
	id pnt;
	while( pnt = [pointEnum nextObject] )
	{
		id pntCpy = [pnt copyWithZone:zone];
		[tmpPoints addObject:pntCpy];
		[pntCpy release];
	}
	tmpPoints = [tmpPoints copy];
	[cp setPoints:tmpPoints];
	[tmpPoints release];

	NSEnumerator *featEnum = [features objectEnumerator];
	id feat;
	while( feat = [featEnum nextObject] )
	{
		id featCpy = [feat copyWithZone:zone];
		[cp addFeature:featCpy];
		[featCpy release];
	}
	
	return cp;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
	[coder encodeObject:points forKey:@"points"];
	[coder encodeObject:features forKey:@"features"];
	[coder encodeObject:NSStringFromRect(face) forKey:@"faceString"];
}
- (id)initWithCoder:(NSCoder *)coder
{
	self = [super init];
	
	points = [[coder decodeObjectForKey:@"points"] retain];
    features = [[coder decodeObjectForKey:@"features"] retain];
    face = NSRectFromString( [coder decodeObjectForKey:@"faceString"] );
	
	return self;
}

- (NSRect)face
{
    return face;
}

- (void)setFace:(NSRect)value
{
    face = value;
}

- (MPT_Feature *)featureWithType:(NSString *)type
{
	NSEnumerator *featureEnum = [features objectEnumerator];
	MPT_Feature *feature;
	while( feature = [featureEnum nextObject] )
	{
		if( [[feature type] isEqualToString:type] )
			return feature;
	}
	return nil;
}
- (NSPoint)leftEye
{
	MPT_Feature *feature = [self featureWithType:@"left_eye"];
	if( feature )
		return [feature location];
	return NSMakePoint(-1.0,-1.0);
}
- (NSPoint)rightEye
{
	MPT_Feature *feature = [self featureWithType:@"right_eye"];
	if( feature )
		return [feature location];
	return NSMakePoint(-1.0,-1.0);
}

- (NSArray *)features
{
    return features;
}
- (void)setFeatures:(NSArray *)value
{
    if( features != value )
    {
        [features release];
        features = [value mutableCopy];
    }
}
- (void)addFeature:(MPT_Feature *)feature
{
	[features addObject:feature];
}

- (float)headTilt
{
	NSPoint leftEye = [self leftEye];
	NSPoint rightEye = [self rightEye];
	
	if( -1 == leftEye.x
		|| -1 == leftEye.y
		|| -1 == rightEye.x
		|| -1 == rightEye.y )
		return 0.0;
	
	float opposite = leftEye.y - rightEye.y;
	float adjacent = leftEye.x - rightEye.x;
	float angle = atan( opposite / adjacent ); // in radians
	return angle * 57.2957795; // (180.0*(r)/M_PI)
}

/** An array of points that defines the face.
 * This can be instead of or in addition to the face rect. Usually it will be set by the
 * face alignment/rotation code. In some cases it won't be a rectangle, which is why it's an array
 * of points.
 */
- (NSArray *)points
{
    return points;
}

- (void)setPoints:(NSArray *)value
{
    if( points != value )
    {
        [points release];
        points = [value retain];
    }
}
@end


@interface MPT_Feature(PrivateMethods)
- (void)setType:(NSString *)value;
- (void)setLocation:(NSPoint)value;
@end

@implementation MPT_Feature
+ (MPT_Feature *)featureOfType:(NSString *)_type AtLocation:(NSPoint)loc
{
	MPT_Feature *feature = [[MPT_Feature alloc] initWithType:_type AtLocation:loc];
	return [feature autorelease];
}

- (id)initWithType:(NSString *)_type AtLocation:(NSPoint)loc
{
	if( self = [super init] )
	{
		[self setType:_type];
		[self setLocation:loc];
		[self setColor:[NSColor redColor]];
		[self setDisplay:YES];
	}
	return self;
}

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

- (id)copyWithZone:(NSZone *)zone
{
	NSString *typeCpy = [[self type] copyWithZone:zone];
	MPT_Feature *cp = [[MPT_Feature alloc] initWithType:typeCpy AtLocation:[self location]];
	
	[typeCpy release];
	
	[cp setSize:[self size]];
	
	NSColor *colorCpy = [[self color] copyWithZone:zone];
	[cp setColor:colorCpy];
	[colorCpy release];
			
	return cp;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
	[coder encodeObject:type forKey:@"type"];
	[coder encodeObject:color forKey:@"color"];
	[coder encodeObject:NSStringFromPoint(location) forKey:@"locString"];
	[coder encodeObject:NSStringFromSize(size) forKey:@"sizeString"];
	[coder encodeBool:display forKey:@"display"];
}
- (id)initWithCoder:(NSCoder *)coder
{
	self = [super init];
	
	type = [[coder decodeObjectForKey:@"type"] retain];
    color = [[coder decodeObjectForKey:@"color"] retain];
    location = NSPointFromString( [coder decodeObjectForKey:@"locString"] );
    size = NSSizeFromString( [coder decodeObjectForKey:@"sizeString"] );
	display = [coder decodeBoolForKey:@"display"];
	
	return self;
}

- (NSString *)type
{
    return type;
}

- (void)setType:(NSString *)value
{
    if( type != value )
    {
        [type release];
        type = [value retain];
    }
}

- (NSPoint)location
{
    return location;
}

- (void)setLocation:(NSPoint)value
{
    location = value;
}

- (NSSize)size
{
    return size;
}

- (void)setSize:(NSSize)value
{
    size = value;
}


- (NSColor *)color
{
    return color;
}

- (void)setColor:(NSColor *)value
{
    if( color != value )
    {
        [color release];
        color = [value retain];
    }
}

- (BOOL)display {
    return display;
}

- (void)setDisplay:(BOOL)value {
    if (display != value) {
        display = value;
    }
}
@end
