
#import "AbstractFilledSquare.h"
#import "EmptySquare.h"			/* for foundAdajacent message decl. */

@implementation AbstractFilledSquare

- (BOOL) acceptsFirstMouse {
    return YES;
}

- (float) color {
    return [self subclassResponsibility: _cmd], 0;	/* ", 0" for -Wall */
}

#define FRACTION  0.6

- drawSelf: (const NXRect *) rects : (int) rectCount {
    double  cx = NX_MIDX(&bounds), cy = NX_MIDY(&bounds);

    [super drawSelf: rects : rectCount];
    PSsetgray([self color]);
    PSarc(cx, cy, FRACTION * bounds.size.width / 2, 0, 360);
    PSfill();
    if ([self isSelected])
	[self select: cx : cy];
    return self;
}

- (BOOL) isMyMove {
    return [[self window] isWhiteMove] == [self isWhite];
}

- (BOOL) isSelected {
    return isSelected;
}

- (BOOL) isWhite {
    return [self subclassResponsibility: _cmd], NO;
}

- mouseDown: (NXEvent *) theEvent {
    if ([self isMyMove])
	[self setIsSelected: YES];
    return self;
}

- mouseEntered: (NXEvent *) theEvent {
    if ([self isSelected] || ([self isMyMove] /* could see if ANY move legal */
					&& ![[self window] isSomeoneSelected]))
	[self setIsHighlighted: YES];
    return self;
}

- mouseUp: (NXEvent *) theEvent {
    id  emptySquare = [[self window] highlightedSquare];

    if (self != emptySquare && [self isSelected]    /* && emptySquare != nil */
					      && [emptySquare isHighlighted]) {
	id     emptyClass = [emptySquare class];
	short  jump = [self distanceTo: emptySquare];

	[[self window] makeSquaresPerform: @selector(capture:)
			             with: [emptySquare become: [self class]]];
	[self setIsSelected: NO];	 /* won't be done by free in become: */
	if (jump > 1)	       /* below since it needs [self window] to work */
	    return [[[self become: emptyClass] window] letOtherColorMove];
	return [[self window] letOtherColorMove];  /* hope any non-nil is OK */
    }
    return [self setIsSelected: NO];
}

- setIsSelected: (BOOL) state {
    [[self window] setIsSomeoneSelected: isSelected = state];
    return [self display];
}

/* Private methods: */

- capture: sender {
    if ([self class] != [sender class] && [self distanceTo: sender] == 1)
	return [self become: [sender class]];
    return self;
}

- checkAdjacencyWith: sender {	    /* can extend below for a toroidal board */
    if ([self isSelected] && [self distanceTo: sender] <= 2)
	[sender foundAdjacent];
    return self;
}

- free {
    if ([self isSelected])		 /* this no longer works right after */
	[[self window] setIsSomeoneSelected: NO];   /* a removeFromSuperview */
    return [super free];
}

#define X_OFFSET  9			/* should really be a % of width */
#define X_WIDTH   4

- select: (double) cx : (double) cy {
    PSsetgray(NX_DKGRAY);
    PSsetlinewidth(X_WIDTH);
    PSmoveto(cx - X_OFFSET, cy + X_OFFSET);
    PSlineto(cx + X_OFFSET, cy - X_OFFSET);
    PSmoveto(cx + X_OFFSET, cy + X_OFFSET);
    PSlineto(cx - X_OFFSET, cy - X_OFFSET);
    PSstroke();
    return self;
}

@end
