#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Vk/VkErrorDialog.h>
#include "VbMotorSwitch.h"
#include "TiburonApp.h"
#include "DmErrno.h"
#include "vbSystem.h"
#include "powerTypes.h"
#include "thrusterDM.h"
#include "powerDM.h"

#define dprintf if (debug) fprintf

VbMotorSwitch::VbMotorSwitch(const char *name, Widget parent)
  : DmGuiObject(name, parent)
{
  _baseWidget = XtVaCreateWidget(name, xmRowColumnWidgetClass, parent, NULL);
  installDestroyHandler();
  
#ifdef ZILCH
  _button = 
    XtVaCreateManagedWidget("button", xmPushButtonWidgetClass, _baseWidget,
			    NULL);
  
  XtAddCallback(_button, XmNactivateCallback, 
		&VbMotorSwitch::buttonCallback, (XtPointer )this);

#endif

  _button = new DynamicButton("button", _baseWidget, 100, 50);
  _button->setActivateCallback(&VbMotorSwitch::buttonCallback, 
			       (XtPointer )this);
  
  _button->show();
  
  char itemName[MaxDmNameLen];
  char *namePtr;
  char errorBuf[errorMsgSize];

  strcpy(itemName, VB_MOTOR_DM_PREFIX);
  namePtr = itemName + strlen(itemName);
  
  strcpy(namePtr, MOTOR_ENABLE_STATUS_DM);
  _dmEnabled = new DmEnumObject(itemName);
  if (_dmEnabled->error())
  {
    _dmEnabled->errorMsg(errorBuf);
    setError(errorBuf);
    return;
  }

  if (addDmObject(_dmEnabled, DmConsumeFlag) == -1)
    return;

  strcpy(namePtr, VB_MOTOR_RUN_DM);
  
  _dmRunState = new DmEnumObject(itemName);
  if (_dmRunState->error())
  {
    _dmRunState->errorMsg(errorBuf);
    setError(errorBuf);
    return;
  }

  if (addDmObject(_dmRunState, DmProvideFlag | DmConsumeFlag) == -1)
    return;

  _dmPowerStatus = new DmEnumObject(VB_MOTOR_SWITCH_STATUS_DM);
  if (_dmPowerStatus->error())
  {
    _dmPowerStatus->errorMsg(errorBuf);
    setError(errorBuf);
    return;
  }

  if (addDmObject(_dmPowerStatus, DmConsumeFlag) == -1)
    return;
  
  if (setConsumePeriod(Aperiodic) == -1)
    return;
  
  _running = Indeterminate;
  updateGui();
}


VbMotorSwitch::~VbMotorSwitch()
{
}


void VbMotorSwitch::updateGui(DM_Item handle)
{
  Boolean debug = False;
  dprintf(stderr, "*** VbMotorSwitch::updateGui()\n");
  
  DM_Time t;
  Errno errno;
  char errorBuf[512];
  Int32 value;

  // Determine if run-switch is ready to be used
  Boolean ready = True;
  
  if ((errno = _dmPowerStatus->read(&value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "VbMotorSwitch::updateGui()", errorBuf);
    setError(errorBuf);
    theErrorDialog->postAndWait(errorBuf);
    return;
  }

  if ((switchStatus )value != SWITCH_ON)
    ready = False;
  
  if ((errno = _dmEnabled->read(&value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "VbMotorSwitch::updateGui()", errorBuf);
    setError(errorBuf);
    theErrorDialog->postAndWait(errorBuf);
    return;
  }

  if ((motorEnableState )value != ENABLE_MOTOR)
    ready = False; 
  
  if (ready)
    XtSetSensitive(_button->baseWidget(), True);
  else
    XtSetSensitive(_button->baseWidget(), False); 
  
  if ((errno = _dmRunState->read(&value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "VbMotorSwitch::updateGui()", errorBuf);
    setError(errorBuf);
    theErrorDialog->postAndWait(errorBuf);
    return;
  }
  _running = value;
  
  Pixel foreground, background;
  char *label;

  if (!ready)
  {
    ((TiburonApp *)theApplication)->powerOffColors(&foreground, &background);
    label = "Motor\nNot Ready";
  }
  else
  {
    if (_running)
    {
      ((TiburonApp *)theApplication)->powerOnColors(&foreground, &background);
      label = "Motor\nRunning";
    }
    else
    {
      ((TiburonApp *)theApplication)->okColors(&foreground, &background);
      label = "Motor\nReady";
    }  
  }
  
  _button->setText(label);
  _button->setColors(foreground, background);
}


void VbMotorSwitch::toggleState()
{

  DM_Time t;
  Errno errno;
  char errorBuf[512];
  int value;
  
  if (_running)
    // Turn motor off
    value = 0;
  else
    // Turn motor on
    value = 1;
  
  t.tv_sec = time(NULL);
  t.tv_usec = 0;
  
  if ((errno = _dmRunState->write(value, &t)) != SUCCESS)
  {
    sprintDmError(errno, "VbMotorSwitch::toggleState()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
    return;
  }
  
  _running = !_running;
}


void VbMotorSwitch::buttonCallback(Widget w,
				   XtPointer clientData,
				   XtPointer callData)
{
  VbMotorSwitch *obj = (VbMotorSwitch *)clientData;
  obj->toggleState();
}
