/*
 * @(#)PyraminxP.h
 *
 * Copyright 1994 - 2014  David A. Bagley, bagleyd AT verizon.net
 *
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of the author not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * This program is distributed in the hope that it will be "useful",
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

/* Private header file for Pyraminx */

#ifndef _PyraminxP_h
#define _PyraminxP_h

#include "xwin.h"
#include "timer.h"
#include "Pyraminx.h"

#ifdef WINVER
extern void destroyPuzzle(HBRUSH brush);
extern void resizePuzzle(PyraminxWidget w);
extern void sizePuzzle(PyraminxWidget w);
extern void initializePuzzle(PyraminxWidget w, HBRUSH brush);
extern void exposePuzzle(PyraminxWidget w);
extern void hidePuzzle(PyraminxWidget w);
extern void selectPuzzle(PyraminxWidget w,
	const int x, const int y, const int control);
extern void releasePuzzle(PyraminxWidget w,
	const int x, const int y, const int shift, const int control);
extern void practicePuzzle(PyraminxWidget w);
extern void randomizePuzzle(PyraminxWidget w);
extern void readPuzzle(PyraminxWidget w);
extern void writePuzzle(PyraminxWidget w);
extern void undoPuzzle(PyraminxWidget w);
extern void redoPuzzle(PyraminxWidget w);
extern void clearPuzzle(PyraminxWidget w);
extern void solvePuzzle(PyraminxWidget w);
extern void incrementPuzzle(PyraminxWidget w);
extern Boolean decrementPuzzle(PyraminxWidget w);
extern void orientizePuzzle(PyraminxWidget w);
extern void stickyModePuzzle(PyraminxWidget w);
extern void periodModePuzzle(PyraminxWidget w, const int mode);
extern void period2ModePuzzle(PyraminxWidget w);
extern void period3ModePuzzle(PyraminxWidget w);
extern void bothModePuzzle(PyraminxWidget w);
extern void speedUpPuzzle(PyraminxWidget w);
extern void slowDownPuzzle(PyraminxWidget w);
extern void toggleSoundPuzzle(PyraminxWidget w);
extern void enterPuzzle(PyraminxWidget w);
extern void leavePuzzle(PyraminxWidget w);
extern void movePuzzleInput(PyraminxWidget w,
	int x, int y, int direction, int shift, int control);
extern int  movePuzzleDir(PyraminxWidget w, const int direction);

#else

/* This gets around C's inability to do inheritance */
typedef struct _PyraminxClassPart {
	int         ignore;
} PyraminxClassPart;

typedef struct _PyraminxClassRec {
	CoreClassPart coreClass;
	PyraminxClassPart pyraminxClass;
} PyraminxClassRec;

extern PyraminxClassRec pyraminxClassRec;
#endif

#ifndef MOVESOUND
#define MOVESOUND "move"
#endif

#define SYMBOL ':'

#define IGNORE_DIR (-1)
#define TOP 0
#define TR 1
#define RIGHT 2
#define BOTTOM 3
#define BL 4
#define LEFT 5
#define COORD 6
#define CW 7
#define CCW 11

#define MAX_FACES 4
#define DOWN 0
#define UP 1
#define MAX_VIEWS 2
#define MAX_SIDES (MAX_FACES/MAX_VIEWS)
#define MAX_ORIENT (3*MAX_SIDES)

typedef struct _moveRecord {
#if 0
	int face, direction, style, control;
#endif
	unsigned short int packed;  /* This makes assumptions on the data. */
	int position;		    /* Do not make assumptions on this one. */
} moveRecord;

typedef struct _MoveStack {
	moveRecord move;
	struct _MoveStack *previous, *next;
} MoveStack;

typedef struct _PyraminxStack {
	MoveStack *currMove, *lastMove, *firstMove;
	int count;
} PyraminxStack;

typedef struct _PyraminxLoc {
	int         face, rotation;
} PyraminxLoc;

typedef struct _PyraminxPart {
	PyraminxLoc *facetLoc[MAX_FACES];
	PyraminxLoc *faceLoc[MAX_SIDES];
	PyraminxLoc *rowLoc[3][MAX_SIDES];
	int         currentFace, currentPosition;
	Boolean     started, cheat, sound;
	Boolean     practice, orient, vertical, mono, reverse, sticky, focus;
	Boolean     scoreOnly, versionOnly;
	int         size, sizeSize, mode;
	int         delay;
	Position    delta;
	Position    facetLength;
	Position    faceLength;
	Position    viewLength;
	Position    sideOffset, orientLineLength, orientDiagLength;
	Point       puzzleSize;
	Point       puzzleOffset, letterOffset;
	GC          frameGC, borderGC, inverseGC;
	GC          faceGC[MAX_FACES];
#ifdef WINVER
	char        userName[81], scoreFile[81], moveSound[81];
	char        faceChar[MAX_FACES];
#else
	int         menu, pixmapSize;
	char       *userName, *scoreFile, *moveSound, *font;
	XFontStruct *fontInfo;
	char       *faceName[MAX_FACES];
	Pixel       foreground, background;
	Pixel       frameColor, borderColor;
	Pixel       faceColor[MAX_FACES];
	XtCallbackList select;
#endif
} PyraminxPart;

typedef struct _PyraminxRec {
	CorePart    core;
	PyraminxPart pyraminx;
} PyraminxRec;

extern PyraminxLoc *startLoc[MAX_FACES];
extern void setPuzzle(PyraminxWidget w, int reason);
extern void movePuzzle(PyraminxWidget w, int face, int position,
	int direction, int style, int control);
extern void movePuzzleDelay(PyraminxWidget w, int face, int position,
	int direction, int style, int control);

extern void solveSomePieces(PyraminxWidget w);
extern void drawAllPieces(PyraminxWidget w);
extern Boolean checkSolved(PyraminxWidget w);
extern void newMoves(PyraminxStack *s);
extern void deleteMoves(PyraminxStack *s);
extern void setMove(PyraminxStack *s,
	int direction, int style, int control, int face, int position);
extern void getMove(PyraminxStack *s,
	int *direction, int *style, int *control, int *face, int *position);
extern int madeMoves(PyraminxStack *s);
extern void flushMoves(PyraminxWidget w, PyraminxStack *s, Boolean undo);
extern int numMoves(PyraminxStack *s);
extern void scanMoves(FILE *fp, PyraminxWidget w, int moves);
extern void printMoves(FILE *fp, PyraminxStack *s);
extern void scanStartPosition(FILE *fp, PyraminxWidget w);
extern void printStartPosition(FILE *fp, PyraminxWidget w);
extern void setStartPosition(PyraminxWidget w);

#endif /* _PyraminxP_h */
