
#import "CubePlane.h"
#import "Plane.h"
#import "Cubicle.h"

extern "C" {
#import <dpsclient/psops.h>
}
extern "Objective-C" {
#import <objc/List.h>
}

#define ZAlloc(CLASS) [CLASS allocFromZone:[self zone]]
enum {FRONT, SIDE, TOP, VSMAX} ViewSides;

static const NXCoord scale = 0.01;
static const NXCoord angle[] = {0.0, 0.85, -0.4};

#define N_FACES 8
static id iconList;
static NXColor colorList[N_FACES] = {
	NX_COLORBLUE, NX_COLORPURPLE, NX_COLORRED,
	NX_COLORMAGENTA, NX_COLORCYAN, NX_COLORYELLOW,
	NX_COLORGREEN, NX_COLORWHITE};

@implementation CubePlane

+ initialize
{
	iconList = [ZAlloc(List) initCount:N_FACES];
	return [super initialize];
}

- initPlane:(Plane *)plane tag:(CubeInt)tag
{
	[super init];
	myPlane = plane;
	myTag = tag;

	return self;
}

-free
{
	delete myPlane;
	return [super free];
}

- resizeTo:(NXPoint)unit
{
				/* Should we unrotate first? */
	switch (myTag) {
	      case FRONT:
		[[self moveTo:0.0 :0.0] sizeTo:(3*unit.x) :(2*unit.y)];
		break;
	      case SIDE:
		[[self moveTo:(3*unit.x) :0.0] sizeTo:unit.x :(3*unit.y)];
		[[self scale:scale :1.0] rotate:angle[SIDE]];
		break;
	      case TOP:	
		[[self moveTo:0.0 :(2*unit.y)] sizeTo:(4*unit.x) :unit.y];
		[[self scale:1.0 :scale] rotate:angle[TOP]];
		break;
		break;
	}

	return self;
}

/* This should be a PSWrap someday */
static void drawFace(NXRect *aRect, CubeFace face)
{
#ifdef GRAY
	const float temp= face/(float)(CubeNSides-1);
	NXSetColor(NXConvertGrayToColor(temp));
#else
	NXSetColor(colorList[face]);
#endif
	PSrectfill(NX_X(aRect), NX_Y(aRect), 
		   NX_WIDTH(aRect), NX_HEIGHT(aRect));

	PSsetgray(NX_BLACK);
	NXFrameRect(aRect);
}

#ifdef THREED
#define DEPTH 1
static const short face[DEPTH] = {-1};
static const short level[DEPTH] = {0};
#else
#define DEPTH 4
static const short face[DEPTH] = {T, -1, -1, T};
static const short level[DEPTH] = {1, 1, 0, 0};
#endif

#define NFACES CubeSide*CubeSide

- drawSelf:(const NXRect *)rects :(int)rectCount
{
	enum {X,Y,XYMAX};
	NXRect oneFace;

	static CubeInt map[VSMAX][NFACES][XYMAX] = 
	    {	  {{0,0},{1,0},{1,1},{0,1}},
		  {{1,0},{0,0},{0,1},{1,1}},
		  {{0,1},{0,0},{1,0},{1,1}} };

	NXCoord size[] = {NX_MIDX(&bounds), NX_MIDY(&bounds)};
	NXCoord off[] = {size[X]/DEPTH, size[Y]/DEPTH};

	for (CubeInt cube = 0; cube < NFACES; cube++) {
		CubeInt* cMap = map[myTag % VSMAX][cube];
		NXCoord base[2][2] = {{0.0, 0.0}, {size[X], size[Y]}};
		short i,j;
		for (i=0; i < DEPTH; i++) {
			NXSetRect(&oneFace, 
				  base[cMap[X]][X], base[cMap[Y]][Y],
				  base[1][X] - base[0][X],
				  base[1][Y] - base[0][Y]);
			drawFace(&oneFace, 
				 myPlane[level[i]].face(cube,face[i]));

			for (j=X; j < XYMAX; j++)
				base[0][j] += off[j];
		}
	}
	return self;
}

/* Need outer Planes different than Inner ones */
@end
