/*
Grzegorz Niemirowski
www.grzegorz.net
*/

#include <stdlib.h>
#include <Xm/Xm.h>
#include <Xm/PushBG.h>
#include <Xm/Form.h>
#include <Xm/MessageB.h>
#include <Xm/SelectioB.h>

void pushed(Widget w, XtPointer client_data, XtPointer call_data);
void msg_ok(Widget w, XtPointer client_data, XtPointer call_data);
int check();

const int M = 3;
const int N = 3;

int board[M][N];

bool cross = false;

int main(int argc, char ** argv) {
	XtAppContext app;
	Widget top_wid, parent, w;

	top_wid = XtVaAppInitialize(&app, "Tic-Tac-Toe", NULL, 0, &argc, argv, NULL, XmNtitle, "Tic-Tac-Toe", NULL);

	
	parent = XtVaCreateManagedWidget("form", xmFormWidgetClass, top_wid, XmNfractionBase, M, XmNwidth, 200, XmNheight, 200, NULL);
 
	for (int y = 0; y < M; y++) {
        	for (int x = 0; x < N; x++) {
            		w = XtVaCreateManagedWidget("   ",
                	xmPushButtonGadgetClass, parent,
	                XmNtopAttachment,    XmATTACH_POSITION,
        		XmNtopPosition,      y,
	                XmNleftAttachment,   XmATTACH_POSITION,
	                XmNleftPosition,     x,
	                XmNrightAttachment,  XmATTACH_POSITION,
	                XmNrightPosition,    x+1,
	                XmNbottomAttachment, XmATTACH_POSITION,
	                XmNbottomPosition,   y+1,
	                NULL);
           		XtAddCallback(w, XmNactivateCallback, pushed, (XtPointer)(y*M+x));
		}
        }

	XtRealizeWidget (top_wid);
	XtAppMainLoop (app);

	return 0;
	}

void msg_ok(Widget w, XtPointer client_data, XtPointer call_data) {
	exit(0);
}

void pushed(Widget w, XtPointer client_data, XtPointer call_data) {
	XmString str;
	char sCircle[] = "O";
	char sCross[] = "X";
	int coord = (long int) client_data;
	int y = coord / M;
	int x = coord % M;
	if (board[y][x]==0) {
		str = XmStringCreateLocalized (cross ? sCross : sCircle);
		XtVaSetValues (w, XmNlabelString, str, NULL);
		XmStringFree (str);
		board[y][x]=cross ? 2 : 1;
		cross = !cross;
	}
	int result = check();
	if (result) {
		char msg1[] = "Game over. Player 1 wins!";
		char msg2[] = "Game over. Player 2 wins!";
		char msg3[] = "Game ended with a draw.";
		XmString xm_string = XmStringCreateLocalized(result==1 ? msg1 : (result==2 ? msg2 : msg3));
		Arg arg[2];
		XtSetArg(arg[0], XmNmessageString, xm_string);
		XtSetArg(arg[1], XmNdialogTitle, xm_string);
		Widget mbox = XmCreateInformationDialog(XtParent(w), "info", arg, 2);
		XmStringFree (xm_string);
		Widget remove = XmMessageBoxGetChild(mbox, XmDIALOG_HELP_BUTTON);
		XtUnmanageChild(remove);
		remove = XmMessageBoxGetChild(mbox, XmDIALOG_CANCEL_BUTTON);
	        XtUnmanageChild(remove);
		XtManageChild(mbox);
		XtAddCallback (mbox, XmNokCallback, msg_ok, NULL);
		XtPopup(XtParent(mbox), XtGrabNone);
	}
}

int check() {
	// check rows
	for(int y=0; y<N; y++) {
		int s = board[y][0];
		if (s) {
			bool match = true;
			for(int x=0; x<M; x++) {
				if (board[y][x]!=s) {
					match = false;
					break;
				}
			}
			if (match) return s;
		}
	}
	// check columns
	for(int x=0; x<M; x++) {
                int s = board[0][x];
		if (s) {
			bool match = true;
                	for(int y=0; y<N; y++) {
				if (board[y][x]!=s) {
					match = false;
					break;
				}
                	}
			if (match) return s;
		}
        }
	// check diagonal
	if (M==N) {
		// left up to right down
		int s = board[0][0];
                if (s) {
                        bool match = true;
                        for(int a=0; a<M; a++) {
                                if (board[a][a]!=s) {
                                        match = false;
                                        break;
                                }
                        }
                        if (match) return s;
                }
		// right up to left down
		s = board[0][M-1];
                if (s) {
                        bool match = true;
                        for(int a=0; a<M; a++) {
                                if (board[a][M-a-1]!=s) {
                                        match = false;
                                        break;
                                }
                        }
                        if (match) return s;
                }
	}
	// check for draw
	bool draw = true;
	for(int y=0; y<N; y++) {
		for(int x=0; x<M; x++) {
			if(board[y][x]==0) return 0;
		}
	}
	return 3;
}
