#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Vk/VkRepeatButton.h>
#include <Vk/VkInfoDialog.h>
#include "Joystick.h"
#include "bigLeftArrow.h"
#include "bigRightArrow.h"
#include "bigUpArrow.h"
#include "bigDownArrow.h"
#include "leftArrow.h"
#include "rightArrow.h"
#include "upArrow.h"
#include "downArrow.h"
#include "DmErrno.h"

#define dprintf if (debug) fprintf

#define ArrowButtonWidth 53
#define ArrowButtonHeight 53

Pixmap Joystick::_coarseLeftImage = NULL;
Pixmap Joystick::_fineLeftImage = NULL;
Pixmap Joystick::_coarseRightImage = NULL;
Pixmap Joystick::_fineRightImage = NULL;
Pixmap Joystick::_coarseUpImage = NULL;
Pixmap Joystick::_fineUpImage = NULL;
Pixmap Joystick::_coarseDownImage = NULL;
Pixmap Joystick::_fineDownImage = NULL;

Joystick::Joystick(const char *name, Widget parent, 
		   DmInt16Object *dmJoystickX,
		   DmInt16Object *dmJoystickY,
		   DmEmptyObject *dmPortLight,
		   DmEmptyObject *dmPortCamera,
		   DmEmptyObject *dmStbdLight,
		   DmEmptyObject *dmStbdCamera)

  : VkComponent(name)
{
  _baseWidget = XtVaCreateWidget(name, xmFormWidgetClass, parent, 
				 XmNfractionBase, 50, NULL);
  installDestroyHandler();

  char errorBuf[errorMsgSize];
  
  Pixel foreground, background;
  XtVaGetValues(_baseWidget, 
		XmNforeground, &foreground,
		XmNbackground, &background,
		NULL);
  
  Display *display = theApplication->display();
  int screenNum = DefaultScreen(display);
  
  if (!_coarseLeftImage && 
      (_coarseLeftImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   bigLeftArrowBits,
				   bigLeftArrowWidth, 
				   bigLeftArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  if (!_coarseRightImage &&
      (_coarseRightImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   bigRightArrowBits,
				   bigRightArrowWidth, 
				   bigRightArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  if (!_coarseUpImage &&
      (_coarseUpImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   bigUpArrowBits,
				   bigUpArrowWidth, 
				   bigUpArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  if (!_coarseDownImage &&
      (_coarseDownImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   bigDownArrowBits,
				   bigDownArrowWidth, 
				   bigDownArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  if (!_fineRightImage &&
      (_fineRightImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   rightArrowBits,
				   rightArrowWidth, 
				   rightArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  if (!_fineLeftImage &&
      (_fineLeftImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   leftArrowBits,
				   leftArrowWidth, 
				   leftArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  if (!_fineUpImage &&
      (_fineUpImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   upArrowBits,
				   upArrowWidth, 
				   upArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  if (!_fineDownImage && 
      (_fineDownImage = 
       XCreatePixmapFromBitmapData(display, RootWindow(display, screenNum),
				   downArrowBits,
				   downArrowWidth, 
				   downArrowHeight,
				   foreground, background,
				   DefaultDepth(display, screenNum))) 
      == False)
  {
  }

  
  _coarseUp = 
    XtVaCreateManagedWidget("coarseUp", 
			    xmPushButtonWidgetClass, _baseWidget,
			    XmNarrowDirection, XmARROW_UP,
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNtopPosition, 0, 
			    XmNbottomPosition, 10,
			    XmNleftPosition, 20,
			    XmNrightPosition, 30,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _coarseUpImage,
			    NULL);

  _fineUp = 
    XtVaCreateManagedWidget("fineUp", 
			    xmPushButtonWidgetClass, _baseWidget, 
			    XmNarrowDirection, XmARROW_UP,
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNtopPosition, 10, 
			    XmNbottomPosition, 20,
			    XmNleftPosition, 20,
			    XmNrightPosition, 30,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _fineUpImage,
			    NULL);

  _coarseRight = 
    XtVaCreateManagedWidget("coarseRight", 
			    xmPushButtonWidgetClass, _baseWidget, 
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNarrowDirection, XmARROW_RIGHT,
			    XmNtopPosition, 20,
			    XmNbottomPosition, 30,
			    XmNleftPosition, 40, 
			    XmNrightPosition, 50,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _coarseRightImage,
			    NULL);

  _fineRight = 
    XtVaCreateManagedWidget("fineRight", 
			    xmPushButtonWidgetClass, _baseWidget, 
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNarrowDirection, XmARROW_RIGHT,
			    XmNtopPosition, 20,
			    XmNbottomPosition, 30,
			    XmNleftPosition, 30,
			    XmNrightPosition, 40,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _fineRightImage,
			    NULL);

  _coarseDown = 
    XtVaCreateManagedWidget("coarseDown", 
			    xmPushButtonWidgetClass, _baseWidget, 
			    XmNarrowDirection, XmARROW_DOWN,
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNtopPosition, 40,
			    XmNbottomPosition, 50,
			    XmNleftPosition, 20,
			    XmNrightPosition, 30,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _coarseDownImage,
			    NULL);

  _fineDown = 
    XtVaCreateManagedWidget("fineDown", 
			    xmPushButtonWidgetClass, _baseWidget,
			    XmNarrowDirection, XmARROW_DOWN,
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNtopPosition, 30,
			    XmNbottomPosition, 40,
			    XmNleftPosition, 20,
			    XmNrightPosition, 30,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _fineDownImage,
			    NULL);

  _coarseLeft = 
    XtVaCreateManagedWidget("coarseLeft", 
			    xmPushButtonWidgetClass, _baseWidget,
			    XmNarrowDirection, XmARROW_LEFT,
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNtopPosition, 20,
			    XmNbottomPosition, 30,
			    XmNleftPosition, 0,
			    XmNrightPosition, 10,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _coarseLeftImage,
			    NULL);
  
  _fineLeft = 
    XtVaCreateManagedWidget("fineLeft", 
			    xmPushButtonWidgetClass, _baseWidget,
			    XmNarrowDirection, XmARROW_LEFT,
			    XmNtopAttachment, XmATTACH_POSITION,
			    XmNbottomAttachment, XmATTACH_POSITION,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNrightAttachment, XmATTACH_POSITION,
			    XmNtopPosition, 20,
			    XmNbottomPosition, 30,
			    XmNleftPosition, 10,
			    XmNrightPosition, 20,
			    XmNwidth, ArrowButtonWidth,
			    XmNheight, ArrowButtonHeight,
			    XmNlabelType, XmPIXMAP,
			    XmNlabelPixmap, _fineLeftImage,
			    NULL);

  XtAddCallback(_coarseUp, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);

  XtAddCallback(_coarseDown, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);

  XtAddCallback(_coarseLeft, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);

  XtAddCallback(_coarseRight, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);

  XtAddCallback(_fineUp, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);

  XtAddCallback(_fineDown, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);

  XtAddCallback(_fineLeft, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);

  XtAddCallback(_fineRight, XmNarmCallback, 
		&Joystick::controlPressCallback,
		(XtPointer )this);


  XtAddCallback(_coarseUp, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);

  XtAddCallback(_coarseDown, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);

  XtAddCallback(_coarseLeft, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);

  XtAddCallback(_coarseRight, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);

  XtAddCallback(_fineUp, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);

  XtAddCallback(_fineDown, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);

  XtAddCallback(_fineLeft, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);

  XtAddCallback(_fineRight, XmNdisarmCallback, 
		&Joystick::controlReleaseCallback,
		(XtPointer )this);


  _portLight = 
    XtVaCreateManagedWidget("portLight", xmPushButtonWidgetClass, 
			    _baseWidget, 
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _coarseLeft,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);

  _portCamera = 
    XtVaCreateManagedWidget("portCamera", xmPushButtonWidgetClass, 
			    _baseWidget, 
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _portLight,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);

  _stbdLight = 
    XtVaCreateManagedWidget("stbdLight", xmPushButtonWidgetClass, 
			    _baseWidget, 
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _coarseRight,
			    XmNrightAttachment, XmATTACH_FORM,
			    NULL);

  _stbdCamera = 
    XtVaCreateManagedWidget("stbdCamera", xmPushButtonWidgetClass, 
			    _baseWidget, 
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _stbdLight,
			    XmNrightAttachment, XmATTACH_FORM,
			    NULL);
  

  XtAddCallback(_portLight, XmNactivateCallback, 
		&Joystick::deviceButtonCallback, this);

  XtAddCallback(_portCamera, XmNactivateCallback, 
		&Joystick::deviceButtonCallback, this);

  XtAddCallback(_stbdLight, XmNactivateCallback, 
		&Joystick::deviceButtonCallback, this);

  XtAddCallback(_stbdCamera, XmNactivateCallback, 
		&Joystick::deviceButtonCallback, this);

  char controlName[MaxControlNameLen];
  sprintf(controlName, "tmacs-%s", name);
  
  _dmJoystickX = dmJoystickX;
  _dmJoystickY = dmJoystickY;
  _dmPortLight = dmPortLight;
  _dmPortCamera = dmPortCamera;
  _dmStbdLight = dmStbdLight;  
  _dmStbdCamera = dmStbdCamera;  
}


Joystick::~Joystick()
{
}


void Joystick::toggleDevice(Widget w)
{
  static struct timezone tz = 
  {
    0, 0
  };

  DmEmptyObject *obj;
  
  if (w == _portLight)
  {
    obj = _dmPortLight;
  }
  else if (w == _portCamera)
  {
    obj = _dmPortCamera;
  }
  else if (w == _stbdLight)
  {
    obj = _dmStbdLight;
  }
  else if (w == _stbdCamera)
  {
    obj = _dmStbdCamera;
  }

  DM_Time t;
  gettimeofday(&t, &tz);
  Errno errno;
  
  if ((errno = obj->write(&t)) != SUCCESS)
  {
    char errorBuf[errorMsgSize];
    sprintDmError(errno, "Joystick::toggleDevice() - ", errorBuf);
    setError(errorBuf);
  }
}


void Joystick::controlPressCallback(Widget w, XtPointer clientData,
					  XtPointer callData)
{
  Joystick *obj = (Joystick *)clientData;
  obj->startMoving(w);

}


void Joystick::controlReleaseCallback(Widget w, XtPointer clientData,
					    XtPointer callData)
{
  Joystick *obj = (Joystick *)clientData;
  obj->stopMoving(w);
}


void Joystick::startMoving(Widget w)
{
  static struct timezone tz = 
  {
    0, 0
  };
  
  Boolean debug = False;
  dprintf(stderr, "startMoving()\n");
  
  Int16 value;
  DmInt16Object *dmAxis;
  
  if (w == _coarseUp)
  {
    dmAxis = _dmJoystickY;
    value = HighTiltRate;
  }
  
  else if (w == _coarseDown)
  {
    dmAxis = _dmJoystickY;
    value = -HighTiltRate;
  }
  
  else if (w == _coarseLeft)
  {
    dmAxis = _dmJoystickX;
    value = -HighPanRate;
  }
  
  else if (w == _coarseRight)
  {
    dmAxis = _dmJoystickX;
    value = HighPanRate;
  }
  
  else if (w == _fineUp)
  {
    dmAxis = _dmJoystickY;
    value = LowTiltRate;
  }
  
  else if (w == _fineDown)
  {
    dmAxis = _dmJoystickY;
    value = -LowTiltRate;
  }
  
  else if (w == _fineLeft)
  {
    dmAxis = _dmJoystickX;
    value = -LowPanRate;
  }
  
  else if (w == _fineRight)
  {
    dmAxis = _dmJoystickX;
    value = LowPanRate;
  }
  
  DM_Time t;
  gettimeofday(&t, &tz);
  Errno errno;
  
  if ((errno = dmAxis->write(value, &t)) != SUCCESS)
  {
    char errorBuf[errorMsgSize];
    sprintDmError(errno, "Joystick::startMoving() - ", errorBuf);
    setError(errorBuf);
  }

  return;
  
}


void Joystick::stopMoving(Widget w)
{
  static struct timezone tz = 
  {
    0, 0
  };

  Boolean debug = False;
  dprintf(stderr, "stopMoving()\n");

  Int16 value = 0;
  DmInt16Object *dmAxis;

  if (w == _coarseUp || w == _coarseDown 
      || w == _fineUp || w == _fineDown)
  {
    dmAxis = _dmJoystickY;
  }
  else
  {
    dmAxis = _dmJoystickX;
  }

  DM_Time t;
  gettimeofday(&t, &tz);
  Errno errno;
  
  if ((errno = dmAxis->write(value, &t)) != SUCCESS)
  {
    char errorBuf[errorMsgSize];
    sprintDmError(errno, "Joystick::startMoving() - ", errorBuf);
    setError(errorBuf);
  }

  return;
  
}


void Joystick::deviceButtonCallback(Widget w,
				    XtPointer clientData,
				    XtPointer callData)
{
  Joystick *obj = (Joystick *)clientData;
  obj->toggleDevice(w);
}


Widget Joystick::deviceButton(IviewDevice device)
{
  Widget w;
  
  switch (device)
  {
    case IviewPortLight:
    w = _portLight;
    break;
    
    case IviewPortCamera:
    w = _portCamera;
    break;
    
    case IviewStbdLight:
    w = _stbdLight;
    break;
    
    case IviewStbdCamera:
    w = _stbdCamera;
    break;
  }
  
  return w;
}











