/*  popup.c

    Copyright (C) 1994	Lambert Klasen & Detlef Steuer
			klasen@asterix.uni-muenster.de
			steuer@amadeus.statistik.uni-dortmund.de

    This file is free source code; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation.

    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.  See
    COPYING for more details.
 */




#include <stdio.h>

#include <X11/Intrinsic.h>
#include <X11/Composite.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/keysym.h>

#include <X11/Xaw/Form.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Text.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/SmeLine.h>
#include <X11/Xaw/MenuButton.h>

#include "xgammon.h"
#include "gammon.h"

Widget popup_shell;

/* diawin.c */
extern void CreateDialogWindow();
extern void CreateTournamentWindow();

/* drawing.c */
extern void DrawDoubler();

/* xgammon.c */
extern void Quit       ();
extern void MenuSelect ();
extern void restart    ();

void CreateXGammonPopup           ();
void ShowComputerAnswerToDoubling ();
int  DoublePopup		  ();
void Info			  ();

void CreateXGammonPopup (X11SET *X11Set)
{
	Arg from[1];
	int i;
	char *menu1_names[10];
	char *menu2_names[10];
	char *menu3_names[10];

	if (!gammon_resource.other_display) {
		menu1_names[0] = "save position <s>";
		menu1_names[1] = "load position <l>"; 
		menu1_names[2] = "save game     <S>"; 
		menu1_names[3] = "load game     <L>";
		menu1_names[4] = "save as ..";
		menu1_names[5] = "load ..";
		menu1_names[6] = NULL;

		menu2_names[0] = "restart     <r>";
		menu2_names[1] = "human vs. compi";
		menu2_names[2] = "compi vs. compi";
		menu2_names[3] = "human vs. human";
		menu2_names[4] = "computer finish";
		menu2_names[5] = "rollout";
		menu2_names[6] = "edit position";
		menu2_names[7] = "mail dump";
		menu2_names[8] = "replay game";
		menu2_names[9] = NULL;
	} else {
		menu1_names[0] = "save position <s>";
		menu1_names[1] = "load position <l>"; 
		menu1_names[2] = "save game     <S>"; 
		menu1_names[3] = "load game     <L>";
		menu1_names[4] = "save as ..";
		menu1_names[5] = "load ..";
		menu1_names[6] = NULL;

		menu2_names[0] = "restart     <r>";
		menu2_names[1] = "mail dump";
		menu2_names[2] = NULL;
	}
	menu3_names[0] = "resign normal";
	menu3_names[1] = "resign gammon";
	menu3_names[2] = "resign backgammon";
	menu3_names[3] = "undo move   <u>";
	menu3_names[4] = NULL;

	X11Set->button_shell = XtCreatePopupShell ("XGammon-Buttons", topLevelShellWidgetClass, X11Set->toplevel, NULL, 0);
	X11Set->form         = XtCreateManagedWidget ("form", formWidgetClass, X11Set->button_shell, NULL, 0);

	/* some buttons to push */

	X11Set->quit = XtCreateManagedWidget ("quit", commandWidgetClass, X11Set->form, NULL, 0);
	XtAddCallback (X11Set->quit, XtNcallback, Quit, NULL);

	/* the file menu */

	XtSetArg (from[0], XtNfromHoriz, X11Set->quit);
	X11Set->file_button = XtCreateManagedWidget ("file", menuButtonWidgetClass, X11Set->form, from, 1);

	X11Set->menu   = XtCreatePopupShell ("menu", simpleMenuWidgetClass, X11Set->file_button, NULL, 0);

	for (i = 0; menu1_names[i]; i++) {
		X11Set->entry  = XtCreateManagedWidget (menu1_names[i], smeBSBObjectClass, X11Set->menu, NULL, 0);
		XtAddCallback (X11Set->entry, XtNcallback, MenuSelect, NULL);
	}

	/* the option menu */

	XtSetArg (from[0], XtNfromHoriz, X11Set->file_button);
	X11Set->option_button = XtCreateManagedWidget ("options", menuButtonWidgetClass, X11Set->form, from, 1);

	X11Set->menu    = XtCreatePopupShell    ("menu", simpleMenuWidgetClass, X11Set->option_button, NULL, 0);

	for (i = 0; menu2_names[i]; i++) {
		X11Set->entry  = XtCreateManagedWidget (menu2_names[i], smeBSBObjectClass, X11Set->menu, NULL, 0);
		XtAddCallback (X11Set->entry, XtNcallback, MenuSelect, NULL);
	}

	/* the game menu */

	XtSetArg (from[0], XtNfromHoriz, X11Set->option_button);
	X11Set->game_button = XtCreateManagedWidget ("game", menuButtonWidgetClass, X11Set->form, from, 1);

	X11Set->menu    = XtCreatePopupShell    ("menu", simpleMenuWidgetClass, X11Set->game_button, NULL, 0);

	for (i = 0; menu3_names[i]; i++) {
		X11Set->entry  = XtCreateManagedWidget (menu3_names[i], smeBSBObjectClass, X11Set->menu, NULL, 0);
		XtAddCallback (X11Set->entry, XtNcallback, MenuSelect, NULL);
	}

	/* finally the textwidgets to display some */

	CreateTournamentWindow (X11Set);
	CreateDialogWindow     (X11Set);
}

void ShowComputerAnswerToDoubling (int accept)
{
	char      *label_string;
	Arg       arg[5];
	Position  x, y;
	Widget	  toplevel;
	Widget    form, label, ok;

	if (gammon_resource.other_display)
		toplevel = Player[turn-1].X11Set.toplevel;
	else
		toplevel = Player[0].X11Set.toplevel;

	/* first here this message */
	sprintf (add_text, "%s doubles.\n", Player[turn-1].name);
	AppendDialogText (LOWER, add_text);

	XtSetArg (arg[0], XtNx, &x);
	XtSetArg (arg[1], XtNy, &y);
	XtGetValues (toplevel, arg, 2);
	x += width/2;                   /* in the middle of the board */
	y += height/2;

	XtSetArg (arg[0], XtNx, x);
	XtSetArg (arg[1], XtNy, y);
	popup_shell = XtCreatePopupShell ("doubling", transientShellWidgetClass, toplevel, arg, 2);

	form = XtCreateManagedWidget ("form", formWidgetClass, popup_shell, NULL, 0);

	if (accept) label_string = " I accept doubling ";
	else	    label_string = " I resign ";
	XtSetArg (arg[0], XtNlabel, label_string);
	label = XtCreateManagedWidget ("label", labelWidgetClass, form, arg, 1);

	/* command button is dummmy */
	XtSetArg (arg[0], XtNfromVert, label);
	ok = XtCreateManagedWidget ("ok", commandWidgetClass, form, arg, 1);

	XtPopup (popup_shell, XtGrabExclusive);
	WaitForEvent(ButtonRelease);

	if (accept) {
		doubler.value *= 2;
		DrawDoubler (doubler.value, doubler.owner);
		sprintf (add_text, "%s accepts the double.\n\n", Player[other-1].name);
	} else {
		sprintf (add_text, "%s gives up.\n\n", Player[other-1].name);
	}
	AppendDialogText (LOWER, add_text);
	XtPopdown (popup_shell);
}

/* DoublePopup()
   this popup is alaways called, when the answer of a human player is expected,
   the difference in layout is checked via the Player[].type.
   then the function simply waits for a button event.
 */

int DoublePopup (void)
{
	Widget toplevel;
	Widget form, label, resign, accept;
	Arg arg[2];
	Position x, y;
	char label_string[128];
	int ret;

	if (gammon_resource.other_display)
		toplevel = Player[other-1].X11Set.toplevel;
	else
		toplevel = Player[0].X11Set.toplevel;


	/* first from here this message */
	sprintf (add_text,"%s doubles.\n", Player[turn-1].name);
	AppendDialogText (LOWER, add_text);

	XtSetArg(arg[0], XtNx, &x);
	XtSetArg(arg[1], XtNy, &y);
	XtGetValues(toplevel, arg, 2);
	x += width/2;                   /* in the middle of the board */
	y += height/2;

	XtSetArg(arg[0], XtNx, x);
	XtSetArg(arg[1], XtNy, y);
	popup_shell = XtCreatePopupShell ("doubling", transientShellWidgetClass, toplevel, arg, 2);

	form = XtCreateManagedWidget ("form", formWidgetClass, popup_shell, NULL, 0);

	if (Player[0].type == HUMAN && Player[1].type == HUMAN) {
		if (turn == BLACK) strcpy (label_string, "  white player:  \n  do you accept doubling?  ");
		else		   strcpy (label_string, "  black player:  \n  do you accept doubling?  ");
	} else {
		strcpy (label_string, "  I'd like to double  \n  do you accept?  ");
	}

	XtSetArg (arg[0], XtNlabel, label_string);
	label = XtCreateManagedWidget ("label", labelWidgetClass, form, arg, 1);

	XtSetArg (arg[0], XtNfromVert, label);
	resign = XtCreateManagedWidget ("resign", commandWidgetClass, form, arg, 1);

	XtSetArg (arg[1], XtNfromHoriz, resign);
	accept = XtCreateManagedWidget ("accept", commandWidgetClass, form, arg, 2);

	XtPopup(popup_shell, XtGrabExclusive);

/* once again an event problem, cause of idontknowwhat or somelikethat,
   the Callback functions are too slow, to get an event and process it,
   before the event loop looks for the next one. So, you have to 
   popdown the shell two times or to try this bullshit here. (can't do better, yet)
   any event other than pressing resign button is accept.
 */

	while (1) {
		XEvent event;
	        XtAppNextEvent (app_con, &event);
	        if (event.type == ButtonRelease) {
		   if (event.xbutton.window == XtWindow (resign)) {
			sprintf (add_text, "%s gives up. %s wins %d point\n\n", Player[other-1].name, Player[turn-1].name, doubler.value);
			AppendDialogText (LOWER, add_text);
	        	XtDispatchEvent (&event);
			ret = RESIGN;
	           	break;
		   }
		   else if (event.xbutton.window == XtWindow (accept)) {
			doubler.value *= 2;
			DrawDoubler (doubler.value, doubler.owner);
			sprintf (add_text,"%s accepts the double.\n\n", Player[other-1].name);
			AppendDialogText (LOWER, add_text);
	        	XtDispatchEvent (&event);
			ret = ACCEPT;
			break;
		   }
	        }
	        XtDispatchEvent (&event);
	}
	XtPopdown (popup_shell);

	return ret;
}

void Info (char *message)
{
	Arg arg[3];
	Position x, y;
	Widget toplevel = Player[turn-1].X11Set.toplevel;
	Widget info_form, info_label, down;

	XtSetArg (arg[0], XtNx, &x);
	XtSetArg (arg[1], XtNy, &y);
	XtGetValues (toplevel, arg, 2);
	x += width/4;                   /* almost the center */
	y += height/2;

	XtSetArg (arg[0], XtNx, x);
	XtSetArg (arg[1], XtNy, y);
	popup_shell = XtCreatePopupShell ("Info", transientShellWidgetClass, toplevel, arg, 2);

	info_form   = XtCreateManagedWidget ("info_form", formWidgetClass, popup_shell, NULL, 0);

	XtSetArg (arg[0], XtNlabel, message);
	info_label = XtCreateManagedWidget ("info_label", labelWidgetClass, info_form, arg, 1);

	XtSetArg (arg[0], XtNfromVert, info_label);
	down = XtCreateManagedWidget ("ok", commandWidgetClass, info_form, arg, 1);

	XtPopup (popup_shell, XtGrabExclusive);

	while (1) {
		XEvent event;
		XtAppNextEvent (app_con, &event);
		if (event.type == KeyPress) {
			KeySym k;
			Modifiers m;
			k = XtGetActionKeysym (&event, &m);
			if (k == ' ' || k == XK_Return) {
				XtPopdown (popup_shell);
				XtDispatchEvent (&event);
				break;
			}
		}
		else if (event.type == ButtonRelease && event.xbutton.window == XtWindow (down)) {
			XtPopdown (popup_shell);
			XtDispatchEvent (&event);
			break;
		}
		XtDispatchEvent (&event);
	}
}
