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

@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 [NXApp isWhiteMove] == [self isWhite];
}

- (BOOL) isSelected {
    return isSelected;
}

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

- letOtherColorMove {
    if (![self isMyMove] && [self hasLegalMove])
	[NXApp allowOtherColorMove];
    return self;
}

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

- mouseEntered: (NXEvent *) theEvent {
    if ([self isSelected] || ([self isMyMove] && [self hasLegalMove]
					      && ![NXApp isSomeoneSelected]))
	[self setIsHighlighted: YES]; /* now only LEGAL moves will highlight */
    return self;
}

- mouseUp: (NXEvent *) theEvent {
    id  emptySquare = [NXApp highlightedSquare];	/* is an EmptySquare */

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

	[NXApp makeSquaresPerform: @selector(capture:)
			     with: [emptySquare become: [self class]]];
	if (jump > 1)
	    [self become: emptyClass];
	else
	    [self setIsSelected: NO];
	return [NXApp letOtherColorMove];   /* hope any non-nil return is OK */
    }
    return [self setIsSelected: NO];
}

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

/* Private methods: */

- calculateScore: sender {
    return [sender countSquareAsWhite: [self isWhite]];
}

- 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;
}

- foundLegalMove {	  /* checkForLegalMoveFrom: below found a legal move */
    hasLegalMove = YES;
    return self;
}

- free {
    if ([self isSelected])
	[NXApp setIsSomeoneSelected: NO];
    return [super free];
}

- (BOOL) hasLegalMove {
    hasLegalMove = NO;
    [NXApp makeSquaresPerform: @selector(checkForLegalMoveFrom:) with: self];
    return hasLegalMove;
}

#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
