#import "BWMainObject.h"
#import "BWOverWorld.h"
#import "BWGameData.h"
#import "BWSideView.h"
#import "Variables.h"

@implementation BWMainObject

# pragma mark -

- (void)awakeFromNib
{
	path = nil;
	romData = nil;
	
	mapScale = 1;
}

# pragma mark -
//
- (IBAction)open:(id)sender
{
	int r;
	NSOpenPanel *op = [NSOpenPanel openPanel];
	[op setAllowedFileTypes:[NSArray arrayWithObject:@"nes"]];
	r = [op runModal];
	if (r != NSOKButton) return;
	
	if (path != nil) [path release];
	path = [[op URL] retain];
	
	[windowOverworld setTitle:[NSString stringWithFormat:@"Sword II - %@",[path lastPathComponent]]];
	
	if (romData != nil) [romData release];
	romData = [[NSMutableData alloc] initWithContentsOfURL:path];
	
	[objGameData open:romData];
	[objOverWorld open:romData];
	[objSideView open:romData];
}
/*
- (IBAction)open:(id)sender
{
	// *** Open Testing *** //
	
	//int r;
	//NSOpenPanel *op = [NSOpenPanel openPanel];
	//[op setAllowedFileTypes:[NSArray arrayWithObject:@"nes"]];
	//r = [op runModal];
	//if (r == NSOKButton) {
		
		if (path != nil) [path release];
		//path = [op URL];
	
		//path = [[NSURL alloc] initWithString:@"file:///Users/sim/Desktop/Hacking/Zelda%202/Zelda%202.nes"];
		path = [[NSURL alloc] initWithString:@"file:///Users/sim/Desktop/Hacking/Zelda%202/Tests/Map%20Tests/Gouin.nes"];
	
		//NSLog(@"Path : %@",path);
		[windowOverworld setTitle:[NSString stringWithFormat:@"Sword II - %@",[path lastPathComponent]]];
		
		if (romData != nil) [romData release];
		romData = [[NSMutableData alloc] initWithContentsOfURL:path];
		//NSLog(@"romData length : %X",(unsigned int)[romData length]);
		//NSLog(@"--------");
	
		[objGameData open:romData];
		[objOverWorld open:romData];
		[objSideView open:romData];
	//}
	//
	unsigned const char *ptr = [romData bytes] + 0x105A1 + 0x10;
	unsigned char n,p;
	unsigned int np,x;
	int i;
	
	for (i=0; i<0x3F; i++) {		// 3F
		n = *ptr++;
		p = *ptr++;
		np = n | p << 8;
		x = np - 0x7000;
		x += 0x108A0;
		printf("%02X%02X -> %04X\n",n,p,x);
	}//
}
*/

- (IBAction)save:(id)sender
{
	//[objGameData save];
	[objOverWorld save];
	//[objSideView save];
	
	if ([romData writeToURL:path atomically:YES]) NSLog(@"Save - OK");
	else NSLog(@"Save - I AM ERROR");
}

# pragma mark -

- (NSColor *)colorForCode:(unsigned char)code
{
	NSColor *color;
	struct sCol tp = nesPal[code];
	float r,g,b;
	
	if (code > 0x3F) code = 0x3F;
	r = (float)tp.r / 255.0;
	g = (float)tp.g / 255.0;
	b = (float)tp.b / 255.0;
	color = [NSColor colorWithDeviceRed:r green:g blue:b alpha:1.0];
	
	return color;
}

# pragma mark -

/*- (unsigned int)stringToHex:(NSString *)str
{
	unsigned int res = 0;
	unsigned short temp;
	unsigned char move = 0x00000000;	// Super Zero !
	
	int i;
	for (i=[str length]-1; i>=0; i--) {
		temp = [[str uppercaseString] characterAtIndex:i];
		if ((temp >= 'A') && (temp <= 'F')) temp -= 0x37;
		else temp -= 0x30;
		res |= temp <<= move;
		move += 4;
	}
	
	return res;
}*/

- (NSImage *)tileWithOffset:(int)os palette:(struct sCol *)pal
{
	const char *p1;
	unsigned char *p2;
	//mapScale = 8;
	p1 = [romData bytes] + os;
	
	int sr = mapScale;		// Scale Ratio
	int wh = sr * 8;
	
	NSImage *tileImage = [[NSImage alloc] initWithSize:NSMakeSize(wh,wh)];
	NSBitmapImageRep *tileRep = [[NSBitmapImageRep alloc] 
				initWithBitmapDataPlanes:NULL
							  pixelsWide:wh
							  pixelsHigh:wh
						   bitsPerSample:8
						 samplesPerPixel:4
								hasAlpha:YES
								isPlanar:NO
						  colorSpaceName:NSDeviceRGBColorSpace
							 bytesPerRow:(wh * 4)
							bitsPerPixel:32];
	
	p2 = [tileRep bitmapData];
	
	int i,j,k1,k2;
	unsigned char b1,b2,cp;
	
	for (i=0; i<8; i++) {
		
		b1 = *p1;
		b2 = *(p1 + 8);
		
		for (j=7; j>=0; j--) {
			
			cp = ((b1 >> j) & 0x01) + (((b2 >> j) & 0x01) * 2);		// Bit Weight (0 1 2 3)
			
			for (k1=0; k1<sr*4; k1+=4) {
				for (k2=0; k2<sr*4; k2+=4) {
					
					if (pal[cp].r == 0xEF) {
						*( ( p2 + (wh * k1) ) + k2) = 0;
						*( ( p2 + (wh * k1) ) + k2 + 1) = 0;
						*( ( p2 + (wh * k1) ) + k2 + 2) = 0;
						*( ( p2 + (wh * k1) ) + k2 + 3) = 0;
					} else {
						*( ( p2 + (wh * k1) ) + k2) = pal[cp].r;
						*( ( p2 + (wh * k1) ) + k2 + 1) = pal[cp].g;
						*( ( p2 + (wh * k1) ) + k2 + 2) = pal[cp].b;
						*( ( p2 + (wh * k1) ) + k2 + 3) = 255;
					}
					
				}
			}
			
			p2 += (sr * 4);
			
		}
		
		p2 += sr * (sr - 1) * 8 * 4;
		p1++;
		
	}
	
	[tileImage addRepresentation:tileRep];
	return tileImage;
}

- (NSImage *)graphicWithTiles:(NSArray *)tilesList type:(unsigned char)size
{
	int h = size & 0x0F;
	int w = (size & 0xF0) >> 4;
	
	if (size == 0) { h = 0x10; w = 0x10; }
	
	int width = w * 8 * mapScale;
	int height = h * 8 * mapScale;
	
	NSImage *tileGraphic = [[[NSImage alloc] initWithSize:NSMakeSize(width,height)] autorelease];
	NSBitmapImageRep *tileRep = [[NSBitmapImageRep alloc] 
				initWithBitmapDataPlanes:NULL
							  pixelsWide:width
							  pixelsHigh:height
						   bitsPerSample:8
						 samplesPerPixel:4
								hasAlpha:YES
								isPlanar:NO
						  colorSpaceName:NSDeviceRGBColorSpace
							 bytesPerRow:(width * 4)
							bitsPerPixel:32];
	
	[tileGraphic addRepresentation:tileRep];
	
	NSImage *imageToDraw;
	NSPoint pt;
	
	[tileGraphic lockFocus];
	int i,j;
	for (i=0; i<h; i++) {
		for (j=0; j<w; j++) {
			imageToDraw = [tilesList objectAtIndex:j+(i*w)];
			pt.y = (h - i - 1) * [imageToDraw size].height;
			pt.x = j * [imageToDraw size].width;
			[imageToDraw drawAtPoint:pt fromRect:NSZeroRect operation:1 fraction:1.0];
		}
	}
	[tileGraphic unlockFocus];
	
	return tileGraphic;
}

- (NSImage *)emptyTile
{
	int sr = mapScale;		// Scale Ratio
	int wh = sr * 8;
	
	NSImage *tileEmpty = [[NSImage alloc] initWithSize:NSMakeSize(wh,wh)];
	NSBitmapImageRep *tileRep = [[NSBitmapImageRep alloc] 
				initWithBitmapDataPlanes:NULL
							  pixelsWide:wh
							  pixelsHigh:wh
						   bitsPerSample:8
						 samplesPerPixel:4
								hasAlpha:YES
								isPlanar:NO
						  colorSpaceName:NSDeviceRGBColorSpace
							 bytesPerRow:(wh * 4)
							bitsPerPixel:32];
	
	unsigned char *imgPtr = [tileRep bitmapData];
	int i;
	for (i=0; i<256; i++) {
		*imgPtr++ = 0;
	}
	
	[tileEmpty addRepresentation:tileRep];
	return tileEmpty;
}

- (void)flipTile:(NSImage *)tile type:(int)flip
{
	NSBitmapImageRep *tileRep = [[tile representations] lastObject];
	
	unsigned int *p1 = (unsigned int *)[tileRep bitmapData];
	unsigned int *p2 = p1;
	int sr = mapScale;
	unsigned int dim = 4 * sr;
	unsigned int res;
	
	unsigned int i,j;
	for (i=0; i<(dim * 2); i++) {
		p2 = p1 + (dim * 2) - 1;
		for (j=0; j<dim; j++) {
			res = *p1;
			*p1 = *p2;
			*p2 = res;
			p1++; p2--;
		}
		p1 += 4 * sr;
	}
}

# pragma mark -

- (NSString *)decToString:(unsigned int)dec
{
	NSNumber *num = [NSNumber numberWithInt:dec];
	return [num stringValue];
}

- (NSString *)hexToString:(unsigned int)hex
{
	NSMutableString *res = [NSMutableString stringWithCapacity:4];
	[res setString:[NSString stringWithFormat:@"%X",hex]];
	
	while ([res length] < 2) {
		[res insertString:@"0" atIndex:0];
	}
	
	return res;
}

- (void)setScale:(int)scale
{
	mapScale = scale;
}

# pragma mark -

- (void)windowDidBecomeKey:(NSNotification *)notification
{
	if (!romData) return;
	
	NSMenu *mainMenu = [NSApp mainMenu];
	
	if ([notification object] == windowOverworld && [menuItemDisplay submenu] != menuDisplayOverworld) {
		if ([menuDisplaySideView retainCount] < 2) [menuDisplaySideView retain];
		[mainMenu setSubmenu:menuDisplayOverworld forItem:menuItemDisplay];
	}
	
	if ([notification object] == windowSideView && [menuItemDisplay submenu] != menuDisplaySideView) {
		if ([menuDisplayOverworld retainCount] < 2) [menuDisplayOverworld retain];
		[mainMenu setSubmenu:menuDisplaySideView forItem:menuItemDisplay];
	}
	
	//NSLog(@"RC : %d %d",[menuDisplayOverworld retainCount],[menuDisplayDungeons retainCount]);
}

# pragma mark -

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
	if (romData == nil) return NO;
	
	int i = NSRunAlertPanel(@"Do you want to save before quitting ?",@"",@"Save",@"Cancel",@"Don't Save");
	if (i == NSAlertAlternateReturn) return NO;
	else if (i == NSAlertOtherReturn) return YES;
	else {
		[self save:nil];
		return YES;
	}
}

@end

