#import <appkit/appkit.h>
#import "Map.h"
#import "IcaoObjects.h"
#import "IcaoController.h"
#import "mapdraw.h"
#import "mapobjects.h"
#import "geometry.h"

@implementation Map


- initFrame:(const NXRect *)frameRect
{
	[super initFrame:(const NXRect *)frameRect];
	[self setFlipped:YES];
	bufferImage = [[NXImage alloc] init];
	if ([bufferImage lockFocus])
	{
		/* Just to make sure the imageRep is allocated */
		PSsetgray(1);
		PSrectstroke(0, 0, 9, 9);
		[bufferImage unlockFocus];
	}
	[[bufferImage bestRepresentation] setSize:&bounds.size];
	[bufferImage setFlipped:YES];
	bufferData.theOrigin.latitude = 0;
	bufferData.theOrigin.longitude = 0;
	bufferData.scale = 250000;
	bufferData.zeroMeridian = 0;
	bufferData.projection = 1;
	bufferData.mapSize = bounds.size;
	bufferData.needsUpdate = YES;
	return self;
}

- (float)heightCmFrom:(float)mapHeight
{
	return (mapHeight * 2.5 / 72);
}

- (float)widthCmFrom:(float)mapWidth
{
	return (mapWidth * 2.5 / 72);
}

- sizeTo:(NXCoord)width :(NXCoord)height
{
	[super sizeTo:width :height];
	mapWidth = width;
	mapHeight = height;
	mapWidthcm = [self widthCmFrom:width];
	mapHeightcm = [self heightCmFrom:height];

	map_initcoord();

	return self;
}

- bufferNeedsUpdate
{
	bufferData.needsUpdate = YES;
	return self;
}

- (BOOL)bufferIsUptodate
{
	if (bufferData.needsUpdate)
		return NO;
	if ((bufferData.theOrigin.longitude != map_origin.longitude)
			|| (bufferData.theOrigin.latitude != map_origin.latitude))
		return NO;
	if (bufferData.scale != map_scale)
		return NO;
	if (bufferData.projection != map_projection)
		return NO;
	if ((bufferData.mapSize.width != bounds.size.width)
			|| (bufferData.mapSize.height != bounds.size.height))
		return NO;
	return YES;
}


- drawSelf:(const NXRect *)rects :(int)rectCount
{
	NXPoint point = {0, bounds.size.height};

	optimizeForMono = atoi(NXGetDefaultValue(APPNAME, IPD_OPTIMIZEMONO));
//If we are drawing(to screen):
	if (NXDrawingStatus == NX_DRAWING)
	{
		screenIsMono = ([window screen]->depth < NX_TwelveBitRGBDepth);
		[super drawSelf:rects :rectCount];
		if (![self bufferIsUptodate])
		{
			int oldType;
			
			oldType = [window backingType];
			[window setBackingType:NX_RETAINED];
			bufferData.theOrigin = map_origin;
			bufferData.scale = map_scale;
			bufferData.projection = map_projection;
			bufferData.mapSize = bounds.size;
			bufferData.needsUpdate = NO;
			if ([self lockFocus])
			{
				PSsetgray(1.0);
				NXRectFill(rects);
#ifdef timetest
				PSW_MarkTime();
				NXPing();
#endif
				[[NXApp delegate] mapChanged:self];
				PSW_defines();
				actually_draw();
#ifdef timetest
				PSW_ReturnTime(&Elapsed);
#endif
				[self unlockFocus];
			}
			[window setBackingType:oldType];
			[bufferImage setSize:&bounds.size];
			[[bufferImage bestRepresentation] setSize:&bounds.size];
			if ([bufferImage lockFocus])
			{
				NXPoint	p = bounds.origin;
				
				/* First use the image to draw the CTRs */
				NXSetColor(NX_COLORCLEAR);
				NXRectFill(&bounds);
				p.y = bounds.size.height;
				drawvisibleobjects(1);
				[bufferImage unlockFocus];
				[bufferImage composite:NX_SOVER toPoint:&p];
			}
									
			if ([bufferImage lockFocus])
			{
				NXRect  rect = bounds;
				
				[self convertRect:&rect toView:nil];
				NXCopyBits([window gState], &rect, &point);
				[bufferImage unlockFocus];
			}
		}
		else
		{
			[bufferImage composite:NX_SOVER toPoint:&point];
		}
	}
//If we are printing:
	if (NXDrawingStatus == NX_PRINTING)
	{
		screenIsMono = YES;

		PSW_defines();
		actually_draw();

	}
	return self;
}

@end

@implementation Map(Printing)

- openSpoolFile:(char *)filename
{
	/* Space for the MarginData */
	NXCoord             mTop, mLeft, mRight, mBottom;

	PrintInfo          *printInfo;
	NXSize              pageSize;

	/* Save the old Size to restore it after printing */
	[self setAutodisplay:NO];
	[self getFrame:&oldFrame];

	printInfo = [NXApp printInfo];
	pageSize = [printInfo paperRect]->size;

	[printInfo getMarginLeft:&mLeft right:&mRight top:&mTop bottom:&mBottom];

	[self sizeTo:pageSize.width - mLeft - mRight:pageSize.height - mTop - mBottom];
	return[super openSpoolFile:filename];
}

- endPSOutput
{
	[super endPSOutput];

	[self sizeTo:NX_WIDTH(&oldFrame) :NX_HEIGHT(&oldFrame)];
	[self setAutodisplay:YES];

	return self;
}

@end