#include <Xm/RowColumn.h> 
#include <Xm/Form.h> 
#include <Vk/VkErrorDialog.h>
#include "HydraulicMotor.h"
#include "powerDM.h"
#include "vbSystem.h"
#include "DmErrno.h"

#define MotorStopMnem "off"
#define MotorSlowMnem "slow"
#define MotorFastMnem "fast"

HydraulicMotor::HydraulicMotor(const char *name, Widget parent)
  : DmGuiObject(name, parent)
{
  _baseWidget = XtVaCreateWidget(name, xmFormWidgetClass, parent, NULL);

  installDestroyHandler();

  char switchDmPrefix[MaxDmNameLen];

  sprintf(switchDmPrefix, "%s%s.", POWER_DM_PREFIX, VB_MOTOR_DM);

  _power = new MotorSwitchGui("power", _baseWidget, 
			      switchDmPrefix,
			      VB_MOTOR_DM_PREFIX,
			      "Hydr Motor",
			      90, 50,
			      500);
	  
  _power->addCallback(MotorSwitchGui::enableStatusChangeCallback, this,
		      (VkCallbackMethod )&HydraulicMotor::powerCallback);

  XtVaSetValues(_power->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_FORM,
		NULL);
  
  _power->show();
  
  _speed = new VkRadioBox("speed", _baseWidget);
  _speed->addItem(MotorStopMnem, FALSE, &HydraulicMotor::speedCallback, this);
  _speed->addItem(MotorSlowMnem, FALSE, &HydraulicMotor::speedCallback, this);
  _speed->addItem(MotorFastMnem, FALSE, &HydraulicMotor::speedCallback, this);

  XtVaSetValues(_speed->baseWidget(),
		XmNleftAttachment, XmATTACH_WIDGET,
		XmNleftWidget, _power->baseWidget(),
		XmNtopAttachment, XmATTACH_FORM,
		NULL);

  _speed->show();

  char itemName[MaxDmNameLen];
  sprintf(itemName, "%s%s", VB_MOTOR_DM_PREFIX, VB_MOTOR_RUN_DM);
  _dmSpeed = new DmEnumObject(itemName);

  if (addDmObject(_dmSpeed, DmConsumeFlag | DmProvideFlag) == -1)
    return;
  
  if (setConsumePeriod(AperiodicGuaranteed) == -1)
    return;

  updateGui();
}


HydraulicMotor::~HydraulicMotor()
{
  delete _power;
  delete _speed;
}


void HydraulicMotor::updateGui(DM_Item handle)
{
  Int32 mode;
  DM_Time t;
  Errno err;
  char errorBuf[errorMsgSize];
  
  if ((err = _dmSpeed->read(&mode, &t)) != SUCCESS)
  {
    sprintDmError(err, "HydraulicMotor::udpateGui()", errorBuf);
    fprintf(stderr, "%s\n", errorBuf);
    return;
  }
  
  switch (mode)
  {
    case VB_MOTOR_OFF:
    break;
    
    case VB_MOTOR_LOW:
    break;
    
    case VB_MOTOR_HIGH:
    break;
    
    default:
    sprintf(errorBuf, "HydraulicMotor::udpateGui() - unknown mode: %d\n",
	    mode);

    setError(errorBuf);
    return;
  }

  _speed->setValue(mode, True);
  
  motorEnableState status = _power->enableStatus();
  
  if (status == ENABLE_MOTOR)
    XtSetSensitive(_speed->baseWidget(), True);
  else
    XtSetSensitive(_speed->baseWidget(), False);
}


void HydraulicMotor::setSpeed(vbMotorRunMode mode)
{
  DM_Time t;
  gettimeofday(&t, NULL);
  
  Errno err;
  char errorBuf[errorMsgSize];
  
  if ((err = _dmSpeed->write(mode, &t)) != SUCCESS)
  {
    sprintDmError(err, "HydraulicMotor::setSpeed()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
    return;
  }
}


void HydraulicMotor::powerCallback(VkCallbackObject *obj,
				   void *clientData,
				   void *callData)
{
  motorEnableState enableStatus = (motorEnableState )callData;

  switch (enableStatus)
  {
    case ENABLE_MOTOR:
    XtSetSensitive(_speed->baseWidget(), True);
    break;
    
    default:
    XtSetSensitive(_speed->baseWidget(), False);
  }
}


void HydraulicMotor::speedCallback(Widget w,
				   XtPointer clientData,
				   XtPointer callData)
{
  XmToggleButtonCallbackStruct *cb = 
    (XmToggleButtonCallbackStruct *)callData;
  
  if (!cb->set)
    return;

  char *wName = XtName(w);
  vbMotorRunMode mode;
  
  if (!strcmp(wName, MotorStopMnem))
    mode = VB_MOTOR_OFF;
  else if (!strcmp(wName, MotorSlowMnem))
    mode = VB_MOTOR_LOW;
  else if (!strcmp(wName, MotorFastMnem))
    mode = VB_MOTOR_HIGH;
  else
    return;
  
  HydraulicMotor *obj = (HydraulicMotor *)clientData;

  obj->setSpeed(mode);
}
