//
//  MPT_AutoTileView.m
//  AUCoderDemo
//
//  Created by Andrew Salamon on 10/23/06.
//  Copyright 2006 Machine Perception Laboratory, University of California San Diego.. All rights reserved.
//

#import "MPT_AutoTileView.h"
#import "MPT_AUView.h"

static const float margin = 8.0;
//static NSRect baseRect = { 0.0, 0.0, 200.0, 65.0 };
static NSRect baseRect = { 0.0, 0.0, 369.0, 243.0 };

@interface MPT_AutoTileView(PrivateMethods)
- (NSPoint)originForSlot:(MPT_ViewSlot)aSlot;
- (void)clearMatrix;
- (void)putView:(MPT_AUView *)view inSlot:(MPT_ViewSlot)slot;
- (MPT_ViewSlot)nextSlotForView:(MPT_AUView *)view;
- (void)debugPrintMatrix;
@end

@implementation MPT_AutoTileView

- (id)initWithFrame:(NSRect)frame
{
    if( self = [super initWithFrame:frame] )
	{
		[MPT_AUView setMargin:margin];
		//baseRect.size = [MPT_AUView defaultFrame].size;
		
        // Initialization code here.
		views = [[NSMutableArray alloc] init];
		
		maxSlot.col = MAXCOL;
		maxSlot.row = [self maxRowsForCurrentHeight];
    }
    return self;
}

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

- (void)setFrameSize:(NSSize)newSize
{
	[super setFrameSize:newSize];
	
	int newMax = [self maxRowsForCurrentHeight];
	if( newMax != maxSlot.row )
	{
		maxSlot.row = newMax;
		[self tileViews];
	}
}

- (BOOL)isFlipped
{
	return YES;
}

- (void)addView:(MPT_AUView *)view
{
	if( ![views containsObject:view] )
	{
		[views addObject:view];
	}
}
- (void)removeView:(MPT_AUView *)view
{
//	[views removeObject:view];
	[view removeFromSuperview];
}

- (void)tileViews
{
	NSEnumerator *viewEnum = [views objectEnumerator];
	MPT_AUView *view;

	[self clearMatrix];
	
	while( view = [viewEnum nextObject] )
	{
		if( [view isEnabled] )
		{
			MPT_ViewSlot nextSlot = [self nextSlotForView:view];
				
			[self putView:view inSlot:nextSlot];
				
			[view setFrameOrigin:[self originForSlot:nextSlot]];
			[view setAutoresizingMask:NSViewMaxXMargin|NSViewMaxYMargin];
			if( [view superview] != self )
			{
				if( [view superview] )
					[view removeFromSuperview];
				[self addSubview:view];
			}
		}
		else
		{
			[view removeFromSuperview];
		}
	}
	
#ifdef xDEBUG
	[self debugPrintMatrix];
#endif
	[self setNeedsDisplay:YES];
}

- (NSPoint)originForSlot:(MPT_ViewSlot)aSlot
{
	NSPoint origin = { 0.0, 0.0 };
		
	origin.x += (baseRect.size.width + margin) * aSlot.col;
	origin.y += (baseRect.size.height + margin) * aSlot.row;
	
	return origin;
}

- (int)maxRowsForCurrentHeight
{
	float height = [self frame].size.height;
	float viewHeight = 0.0;
	int rows = 0;
	
	while( viewHeight < height )
	{
		viewHeight += baseRect.size.height;
		if( viewHeight <= height )
			++rows;
		viewHeight += margin;
	}
	
	return ((rows > MAXROW)?MAXROW:rows);
}

- (void)clearMatrix
{
	for( int row = 0; row < MAXROW; ++row )
		for( int col = 0; col < MAXCOL; ++col )
			matrix[row][col] = nil;
}

- (void)putView:(MPT_AUView *)view inSlot:(MPT_ViewSlot)startSlot
{
	int scale = [view scale];
	for( int row = startSlot.row; row < (startSlot.row+scale); ++row )
		for( int col = startSlot.col; col < (startSlot.col+scale); ++col )
			matrix[row][col] = view;
}

- (MPT_ViewSlot)nextSlotForView:(MPT_AUView *)view
{
	MPT_ViewSlot next = { -1, -1 };
	int scale = [view scale];
	for( int col = 0; col <= (MAXCOL-scale); ++col )
	{
		for( int row = 0; row <= (maxSlot.row-scale); ++row )
		{
			BOOL ok = YES;
			for( int irow = row; (irow < (row+scale)) && ok; ++irow )
			{
				for( int icol = col; (icol < (col+scale)) && ok; ++icol )
				{
					if( nil != matrix[irow][icol] )
						ok = NO;
				}
			}
			if( ok )
			{
				next.row = row;
				next.col = col;
				return next;
			}
		}
	}
	return next;
}

- (void)debugPrintMatrix
{
	NSMutableDictionary *letters = [NSMutableDictionary dictionary];
	char ch = 'A';
	
	// Fill in the letters dictionary first, by columns so the letter order matches better the AU View layout order
	for( int col = 0; col < MAXCOL; ++col )
	{
		for( int row = 0; row < maxSlot.row; ++row )
		{
			if( matrix[row][col] != nil )
			{
				NSNumber *view = [NSNumber numberWithInt:(int)matrix[row][col]];
				NSString *letter = [letters objectForKey:view];
				if( !letter )
				{
					letter = [NSString stringWithFormat:@"%c",ch];
					[letters setObject:letter forKey:view];
					++ch;
				}
			}
		}
	}
	
	for( int row = 0; row < maxSlot.row; ++row )
	{
		NSMutableString *rowString = [NSMutableString string];
		for( int col = 0; col < MAXCOL; ++col )
		{
			if( matrix[row][col] != nil )
			{
				NSNumber *view = [NSNumber numberWithInt:(int)matrix[row][col]];
				NSString *letter = [letters objectForKey:view];
				if( !letter )
				{
					letter = [NSString stringWithFormat:@"%c",ch];
					[letters setObject:letter forKey:view];
					++ch;
				}
				[rowString appendString:letter];
			}
			else
			{
				[rowString appendString:@" "];
			}
		}
		printf( "%s\n", [rowString UTF8String] );
	}
	printf( "\n" );
}

@end
