#include "XawDisplays.h"
#include "XawScreen.h"
#include "displays.h"

#include "city.h"
#include "global.h"
#include "world.h"
#include "keyboard.h"

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/Box.h>

extern void exposeNotify(Widget, WDisplay *, XEvent* , Boolean*);
extern void getEvent(Widget, WDisplay *, XEvent *, Boolean *);
#define Xawscreen ((XawScreen *)screen)

int XawDisplayData::started = 0;

XawDisplayData::~XawDisplayData()
{
  XtPopdown(shell);
  XtDestroyWidget(shell);
}

void XawDisplayData::ExposeNotify(int x, int y, int width, int height) {
  XCopyArea(dpy, pix, window, screen->gc, x, y, width, height, x, y);
}

XawDisplayData::XawDisplayData(X11Screen *scr, Display *display, char *name) : X11DisplayData(scr, display)
{
  if (!started) {
    shell =  Xawscreen->top;
    started = 1;
  }
  else
    shell =  XtAppCreateShell("shell", name, shellWidgetClass, dpy, NULL, 0);

  XawFrame = XtCreateManagedWidget("frame", formWidgetClass, shell, NULL, 0);
  topbox = XtVaCreateManagedWidget("box", boxWidgetClass, XawFrame,
				   XtNorientation, XtorientHorizontal,
				   XtNborderWidth, 0,
				   NULL);
}

void
XawDisplayData::Map()
{
  XtRealizeWidget(shell);
  window = XtWindow(canvas);
  frame = XtWindow(shell);
  Clear();
}

void
XawDisplayData::CreateDrawingArea(int w, int h, WDisplay *window)
{
  width = w; height = h;
  // pixmap as save area for "canvas"
  pix = XCreatePixmap(dpy, XRootWindowOfScreen(XtScreen(XawFrame)),
		      width, height,
		      DefaultDepthOfScreen(XtScreen(XawFrame)));
  XFillRectangle(dpy, pix, screen->gc, 0, 0, width, height);
  
  canvas = XtVaCreateManagedWidget("canvas", labelWidgetClass, XawFrame,
				   XtNlabel, "",
				   XtNfromVert, topbox,
				   XtNtop, XawChainTop,
				   XtNwidth, width,
				   XtNheight, height,
				   XtNbackground, BlackPixel(dpy, DefaultScreen(dpy)),
				   NULL);

  XtAddEventHandler(canvas, ExposureMask, False, exposeNotify, window);
  XtAddEventHandler(canvas, KeyReleaseMask | ButtonReleaseMask , False, getEvent, window);
}

struct callbackData {
  callbackData(void (*f)(void *), void *data) {callback = f; call_data = data;}
  void (*callback)(void *);
  void *call_data;
};

void buttonHandler(Widget /*w*/, callbackData *data, XtPointer /*call*/) {
  data->callback(data->call_data);
}

void
XawDisplayData::AddButton(char *name, void (*callback)(void *), void*call_data)
{
  Widget button = XtVaCreateManagedWidget(name, commandWidgetClass, topbox,
					  XtNlabel, name,
					  NULL);
  XtAddCallback(button, XtNcallback, buttonHandler, new callbackData(callback, call_data));
}

struct menuCallbackData {
  menuCallbackData(void (*f)(void*, void*), void *calldata, void *menudata)
    { callback = f; call_data = calldata; menu_data = menudata; }
  void (*callback)(void *, void *);
  void *call_data;
  void *menu_data;
};

void menuNotify(Widget, menuCallbackData *data, XtPointer) {
  data->callback(data->menu_data, data->call_data);
}

void XawDisplayData::AddMenu(char *name, MenuItem *list,
			    void (*callback)(void *, void *), void *call_data)
{
  char text[50];

  Widget menu = XtVaCreatePopupShell(name, simpleMenuWidgetClass, shell,
				     NULL);
  for (int i = 0; list[i].line != NULL; i++) {
    sprintf(text, "%sItem%d", name, i);
    Widget item = XtVaCreateManagedWidget(text, smeBSBObjectClass, menu,
					  XtNlabel, list[i].line,
					  NULL);
    XtAddCallback(item, XtNcallback, menuNotify, new menuCallbackData(callback, call_data, list[i].return_data));
  }
  
  sprintf(text, "%sButton", name);
  XtVaCreateManagedWidget(text, menuButtonWidgetClass, topbox,
			  XtNlabel, name,
			  XtNmenuName, name,
			  NULL);
}

// MapDisplay

XawMapDisplay::XawMapDisplay(World *w, Player *p) : MapDisplay(w, p) {
  CreateWindow();
}

XawMapDisplay::~XawMapDisplay() {;}

XawMapDisplay::XawMapDisplay() : MapDisplay() {
  CreateWindow();
}

void
XawMapDisplay::CreateWindow()
{
  data = new XawDisplayData((X11Screen *)screen, Xawscreen->dpy, "Civ");
  Setup();

#define data ((XawDisplayData *)data)
  mesg = XtVaCreateManagedWidget("statusMesg", labelWidgetClass, data->topbox,
				 XtNwidth, 200,
				 XtNlabel, "Initializing",
				 "borderWidth", 0,
				 NULL);
  data->Map();
}

void XawMapDisplay::DisplayMessage(char *str, int /*color*/) {
  XtVaSetValues(mesg, XtNlabel, str, NULL);
}

void XawMapDisplay::BlitMap(int x1, int y1, int w, int h, int x2, int y2)
{
  /* XCopyArea(Xawscreen->dpy, data->window, data->window, Xawscreen->gc,
	    x1*SquareWidth+HorizSpace, y1*SquareHeight+VertSpace,
	    w*SquareWidth, h*SquareHeight,
	    x2*SquareWidth+HorizSpace, y2*SquareHeight+VertSpace);*/
}

// citydisplay

XawCityDisplay::XawCityDisplay(City *cityp, Player *owner) : CityDisplay(cityp, owner)
{
  data = new XawDisplayData((X11Screen *)screen, Xawscreen->dpy, cityp->name);

  Setup();
  data->Map();
  Update();
}

XawCityDisplay::~XawCityDisplay()
{;}

// textDisplay

XawtextDisplay::XawtextDisplay(int x, int y) : TextDisplay(x,y)
{
  data = new XawDisplayData((X11Screen *)screen, Xawscreen->dpy, "Civ");
  Setup();
  data->Map();
}

XawtextDisplay::~XawtextDisplay() {;}
