//
//  AppController.m
//  Rat
//
//  Created by Curtis Jones on 2009.11.10.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import "AppController.h"

@implementation AppController

/**
 *
 *
 */
- (void)dealloc
{
	[mazeView release];
	[scrollView release];
	
	[super dealloc];
}

/**
 *
 *
 */
- (void)awakeFromNib
{
	CFDataRef pixelData;
	CGImageRef image;
	CGDataProviderRef dataProvider;
	
	// initialize the ratlib library. this only needs to be done once.
	ratlib_init();
	
	if (NULL == (dataProvider = CGDataProviderCreateWithFilename( [[[NSBundle mainBundle] pathForResource:@"maze" ofType:@"png"] UTF8String] ))) {
		NSLog(@"%s.. failed to CGDataProviderCreateWithFilename\n", __PRETTY_FUNCTION__);
		return;
	}
	
	if (NULL == (image = CGImageCreateWithPNGDataProvider(dataProvider, NULL, NO, kCGRenderingIntentDefault))) {
		NSLog(@"%s.. failed to CGImageCreateWithPNGDataProvider\n", __PRETTY_FUNCTION__);
		return;
	}
	
	if (NULL == (pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image)))) {
		NSLog(@"%s.. failed to CGDataProviderCopyData\n", __PRETTY_FUNCTION__);
		return;
	}
	
	// create a new image with some image data and parameters.
	mImage = ratlib_image(CFDataGetBytePtr(pixelData), 0, CGImageGetBitsPerPixel(image)/8, CGImageGetWidth(image), CGImageGetHeight(image));
	
	// create a new session. ratlib supports multiple simultaneous sessions. each session has a single
	// image associated with it. the image data is not modified and can be shared between multiple 
	// sessions
	mSession = ratlib_session(mImage);
	
	mazeView = [[MazeView alloc] initWithFrame:CGRectMake(0., 0., 100., 100.)];
	mazeView.target = self;
	mazeView.selector = @selector(mouseDown:);
	mazeView.session = mSession;
	mazeView.image = image;
	
	// the scroll view is in the main window and holds the maze image
	scrollView = [[NSScrollView alloc] initWithFrame:[[theWindow contentView] frame]];
	[scrollView setHasVerticalScroller:YES];
	[scrollView setHasHorizontalScroller:YES];
	[scrollView setBorderType:NSNoBorder];
	[scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
	[scrollView setDocumentView:mazeView];
	
	[theWindow setContentView:scrollView];
	[theWindow makeKeyAndOrderFront:nil];
	
	/*
	CGImageRelease(image);
	CGDataProviderRelease(dataProvider);
	*/
}





#pragma mark -
#pragma mark UI Callbacks

/**
 *
 *
 */
- (IBAction)setBegPoint:(id)sender
{
	mTargetModeBeg = TRUE;
	mTargetModeEnd = FALSE;
	
	[mazeView setTargetCursor:TRUE];
}

/**
 *
 *
 */
- (IBAction)setEndPoint:(id)sender
{
	mTargetModeBeg = FALSE;
	mTargetModeEnd = TRUE;
	
	[mazeView setTargetCursor:TRUE];
}

/**
 *
 *
 */
- (IBAction)doActionSolve:(id)sender
{
	if (mSession->begpoint == NULL || mSession->endpoint == NULL) {
		NSLog(@"%s.. must set a begin and end point before solving.", __PRETTY_FUNCTION__);
		return;
	}
	
	NSLog(@"%s.. starting thread...", __PRETTY_FUNCTION__);
	[NSThread detachNewThreadSelector:@selector(solveThread:) toTarget:self withObject:self];
}

/**
 *
 *
 */
- (IBAction)doActionSave:(id)sender
{
	uint32_t bytes;
	CGContextRef context;
	CGColorSpaceRef colorSpace;
	CGImageRef image;
	
	colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
	bytes = 4 * mSession->image->width * mSession->image->height;
	
	if (NULL == (context = CGBitmapContextCreate(NULL, mSession->image->width, mSession->image->height, 8, 4*mSession->image->width, colorSpace, kCGImageAlphaPremultipliedLast))) {
		NSLog(@"%s.. failed to CGBitmapContextCreate. Sorry.", __PRETTY_FUNCTION__);
		return;
	}
	
	[mazeView drawRect:NSMakeRect(0, 0, mSession->image->width, mSession->image->height) inContext:context];
	
	if (NULL == (image = CGBitmapContextCreateImage(context))) {
		NSLog(@"%s.. failed to CGBitmapContextCreateImage. Sorry.", __PRETTY_FUNCTION__);
		return;
	}
	
	NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithCGImage:image];
	NSData *imageData = [imageRep representationUsingType:NSPNGFileType properties:nil];
	[imageData writeToFile:[@"~/Desktop/Solution.png" stringByExpandingTildeInPath] atomically:TRUE];
	
	[imageRep release];
	CGImageRelease(image);
	CGContextRelease(context);
	CGColorSpaceRelease(colorSpace);
}





#pragma mark -
#pragma mark NSResponder

- (void)mouseDown:(NSEvent*)theEvent 
{
	NSLog(@"%s..", __PRETTY_FUNCTION__);
	
	if (!mTargetModeBeg && !mTargetModeEnd)
		return;
	
	NSPoint point = [mazeView convertPoint:[theEvent locationInWindow] fromView:nil];
	ratlibpoint_t *point2 = ratlib_point(point.x, mSession->image->height - point.y - 1);
	
	if (mTargetModeBeg) {
		ratlibsession_setbeg(mSession, point2);
		[[NSNotificationCenter defaultCenter] postNotificationName:@"MazeBeginPointSet" object:nil];
	}
	else if (mTargetModeEnd) {
		ratlibsession_setend(mSession, point2);
		[[NSNotificationCenter defaultCenter] postNotificationName:@"MazeEndPointSet" object:nil];
	}
	
	mTargetModeBeg = FALSE;
	mTargetModeEnd = FALSE;
	
	[mazeView setTargetCursor:FALSE];
	
	ratlibpoint_release(point2);
}





#pragma mark -
#pragma mark Solver

- (void)solveThread:(id)arg
{
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	ratlibsession_t *session = mSession;
	
	[self performSelectorOnMainThread:@selector(disableSolveMenuItem) withObject:nil waitUntilDone:FALSE];
	
	ratlibsession_solve(session);
	[mazeView setNeedsDisplay:TRUE];
	
	[self performSelectorOnMainThread:@selector(enableSolveMenuItem) withObject:nil waitUntilDone:FALSE];
	
	[pool release];
}

- (void)disableSolveMenuItem
{
	[solveItem setEnabled:FALSE];
}

- (void)enableSolveMenuItem
{
	[solveItem setEnabled:TRUE];
}

@end
