
// Handles putting temporary text in the game field.

#import <gamekit/gamekit.h>
#import <daymisckit/daymisckit.h>
#import <dpsclient/psops.h>

static BOOL classInitialized = NO;

@implementation GKTextActor

+ initialize
{
	id ret = [super initialize];
	// we want to make sure that the text pswraps have been initialized.
	if ((self == [GKTextActor class]) && (!classInitialized)) {
		GKTextSetUp();
		classInitialized = YES;
	}
	return ret;
}

- init
{
	NXPoint zero = { 0.0, 0.0 };
	return [self initAtPoint:&zero pointSize:GK_DEFAULTPOINTSIZE];
}

- initAtPoint:(const NXPoint *)aPoint pointSize:(float)points
{	// shouldn't ever really use this, but then again, might as well
	// have it set up a useful text string!
	return [self initWithString:GK_DEFAULTTEXT
			atPoint:aPoint pointSize:points];
}

- initWithInt:(int)aNumber atPoint:(const NXPoint *)aPoint
		pointSize:(float)points
{
	char tempString[32];
	sprintf(tempString, "%d", aNumber);
	return [self initWithString:tempString atPoint:aPoint pointSize:points];
}

- initWithString:(const char *)aString atPoint:(const NXPoint *)aPoint
		pointSize:(float)points
{
	NXRect tempRect;
	id ret = [super init];
	doDraw = YES; visible = YES; blinking = NO; doErase = NO;
	timeLeftOnScreen = 48; blinkPeriod = 4;
	pointSize = points;
	if (!text) text = [[DAYString alloc] init];
	if (!fontName) fontName = [[DAYString alloc] init];
	[fontName setStringValue:"Helvetica"];
	[text setStringValue:aString];
	GK_COPY_VECTORS(&(boundingBox.origin), aPoint);
	// calculate the text size (our bounding box)
	[self getBoundingBox:&tempRect];
	return ret;
}

- (int)timeLeftOnScreen { return timeLeftOnScreen; }
- (int)blinkPeriod { return blinkPeriod; }
- (BOOL)blinking { return blinking; }
- (const char *)fontName { return [fontName stringValue]; }

- getBoundingBox:(NXRect *)box		// obtain the true bounding box
{	// we have to do it this way 'cause descenders in the text can shift
	// the box down from the drawing origin...
	NXRect tempRect = { { 0.0, 0.0 }, { 0.0, 0.0 } };
	float x, y, width, height;
	GKborderedTextBoundingBox((char *)[text stringValue],
			&x, &y, &width, &height);
	NXSetRect(&tempRect, x + NX_X(&boundingBox),
			y + NX_Y(&boundingBox), width, height);
	NX_WIDTH(&boundingBox) = width;
	NX_HEIGHT(&boundingBox) = height;
	GK_COPY_RECT(box, &tempRect);
	return self;
}

- setFontName:(const char *)name
{
	[fontName setStringValue:name];
	return self;
}

- setTimeLeftOnScreen:(int)anInt
{
	timeLeftOnScreen = anInt;
	return self;
}

- setBlinkPeriod:(int)anInt
{
	blinkPeriod = anInt;
	[self setBlinking:(anInt != 0)];
	return self;
}

- setBlinking:(BOOL)anInt
{
	blinking = anInt;
	visible = YES;
	doDraw = YES;
	return self;
}

- eraseInDirtPile:dirtPile
{ // no need to erase us yet.
	if (timeLeftOnScreen < 1) {
		// tell the stage to remove us after this cycle; we're going away
		[self leaveTheStage];
		doErase = YES;
	}
	if (doErase) { // do the erase if we're blinking
		float x, y, width, height;
		GKborderedTextBoundingBox((char *)[text stringValue],
				&x, &y, &width, &height);
		doErase = NO;
		[dirtPile addRegion:(x + GK_VECTOR_X(&lastDrawnLocation))
					:(y + GK_VECTOR_Y(&lastDrawnLocation)) :width :height];
		return self;
	}
	return self;
}

- markInDirtPile:dirtPile
{ // only need to mark the firt time we draw since we are effectively static
	if (doDraw) {
		float x, y, width, height;
		GKborderedTextBoundingBox((char *)[text stringValue],
				&x, &y, &width, &height);
		doErase = NO;
		[dirtPile addRegion:(x + GK_VECTOR_X(&lastDrawnLocation))
					:(y + GK_VECTOR_Y(&lastDrawnLocation)) :width :height];
		return self;
	}
	return self;
}

- moveOneFrame
{	// Decrease the time left on screen every time we "move".
	[super moveOneFrame];
	timeLeftOnScreen--;
	if (!(timeLeftOnScreen % blinkPeriod)) {
		visible = !visible; // turn it on or off
		doDraw = YES;	// make sure the new state is redrawn
		if (!visible) doErase = YES;
	}
	return self;
}

- drawActorWithOffset:(NXPoint *)offset	// draw the actor
{
	if (timeLeftOnScreen < 1) return self;  // don't draw; we're gone
	doDraw = NO;
	if (!visible) return self;
	// We always render, even though we don't always mark the DirtPile,
	// because some other actor may have overwritten us...
	// render the text; white text with a black outline around it.
	PSselectfont([fontName stringValue], pointSize);
	GKdrawBorderedText((offset->x + NX_X(&boundingBox)),
			(offset->y + NX_Y(&boundingBox)), (char *)[text stringValue]);
	return self;
}

@end
