#include "XmDisplays.h"
#include "XmScreen.h"
#include "displays.h"

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

#ifdef HAVE_X11_XMU_EDITRES_H
# include <X11/Xmu/Editres.h>
#endif
#include <X11/Intrinsic.h>
#include <Xm/DrawingA.h>
#include <Xm/ScrolledW.h>
#include <Xm/List.h>
#include <Xm/MessageB.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/TextF.h>

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

int XmDisplayData::started = 0;

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

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

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

  XmFrame = XtCreateManagedWidget("frame", xmFormWidgetClass, shell, NULL, 0);
  panel = XtVaCreateManagedWidget("panel", xmRowColumnWidgetClass, XmFrame,
				  XmNorientation, XmHORIZONTAL,
				  NULL);
}

void XmDisplayData::Map()
{
  XtRealizeWidget(shell);
  window = XtWindow(canvas);
  frame = XtWindow(XmFrame);
}

/*void WDisplayData::BitBlt(int sx, int sy, int w, int h, int dx, int dy)
{
  XCopyArea(screen->dpy, window, window, screen->gc, sx, sy, w, h, dx, dy);
}*/

void
XmDisplayData::CreateDrawingArea(int w, int h, WDisplay *window)
{
  width = w; height = h;
  // pixmap as save area for "canvas"
  pix = XCreatePixmap(dpy, XRootWindowOfScreen(XtScreen(XmFrame)),
		      width, height,
		      DefaultDepthOfScreen(XtScreen(XmFrame)));
  XFillRectangle(dpy, pix, screen->gc, 0, 0, width, height);
  
  canvas = XtVaCreateManagedWidget("canvas", xmDrawingAreaWidgetClass, XmFrame,
					  //XmNtopAttachment, XmATTACH_WIDGET,
					  //XmNtopWidget, panel,
					  XmNwidth, width,
					  XmNheight, height,
					  XmNbackground, BlackPixel(dpy, DefaultScreen(dpy)),
					  NULL);
  XtAddCallback(canvas, XmNexposeCallback, exposeNotify, window);
  XtAddCallback(canvas, XmNinputCallback, 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
XmDisplayData::AddButton(char *name, void (*callback)(void *), void*call_data)
{
  Widget button = XtVaCreateManagedWidget(name, xmPushButtonWidgetClass, panel,
					  XmNlabelString, name,
					  NULL);
  XtAddCallback(button, XmNactivateCallback, 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 XmDisplayData::AddMenu(char *name, MenuItem *list,
			    void (*callback)(void *, void *), void *call_data)
{
  // needs to be written for Motif this is the Xaw version
  /* 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);
  Widget menuButton = XtVaCreateManagedWidget(text, menuButtonWidgetClass, topbox,
					      XtNlabel, name,
					      XtNmenuName, name,
					      NULL);*/
}

// MapDisplay

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

XmMapDisplay::~XmMapDisplay() {;}

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

void
XmMapDisplay::CreateWindow()
{
  data = new XmDisplayData((X11Screen *)screen, Xmscreen->dpy, "Civ");
  Setup();

#define data ((XmDisplayData *)data)
  mesg = XtVaCreateManagedWidget("statusMesg", xmLabelWidgetClass, data->panel,NULL);
  data->Map();
}

void XmMapDisplay::DisplayMessage(char *str, int color)
{
  XtVaSetValues(mesg,
		XtVaTypedArg, XmNlabelString, XtRString, str, 1+strlen(str),
		NULL);
}

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

// citydisplay

XmCityDisplay::XmCityDisplay(City *cityp, Player *owner) : CityDisplay(cityp, owner)
{
  data = new XmDisplayData((X11Screen *)screen, Xmscreen->dpy, cityp->name);

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

XmCityDisplay::~XmCityDisplay()
{;}

// textDisplay

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

XmtextDisplay::~XmtextDisplay() {;}
