#include <Xm/Frame.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/Label.h>
#include <Xm/ArrowB.h>
#include <Xm/Scale.h>
#include <xpm.h>
#include <Vk/VkErrorDialog.h>
#include "MidwaterGui.h"
#include "toolsledNames.h"
#include "midwaterNames.h"
#include "powerDM.h"
#include "DmErrno.h"
#include "netNanny.xpm"
#include "TiburonApp.h"
 
#define dprintf if (debug) fprintf


SwingArm::SwingArm(const char *name, Widget parent, Side side,
		   MidwaterDm *dmItems, const char *platformName)
  : DmGuiObject(name, parent)
{
  _baseWidget = XtVaCreateWidget(name, xmFrameWidgetClass, parent, 
				 NULL);
  
  installDestroyHandler();
  
  Widget mgr = 
    XtVaCreateWidget("mgr", xmRowColumnWidgetClass, _baseWidget,
		     XmNorientation, XmVERTICAL, 
		     NULL);
  
  Widget label = 
    XtVaCreateManagedWidget("label", xmLabelWidgetClass, mgr, NULL);
  
  Widget mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, mgr,
		     XmNorientation, XmHORIZONTAL,
		     NULL);

  char itemName[MaxDmNameLen];
  DmObject::buildPrefix(itemName, platformName, PowerName, 0);

  char *namePtr = itemName + strlen(itemName);
  
  if (side == PortSide)
    strcpy(namePtr, PORT_SA_DEPLOY_DM);
  else
    strcpy(namePtr, STBD_SA_DEPLOY_DM);

  _deploy = new MomentaryPowerSwitch("deploy", mgr2, itemName, "Deploy",
				     100, 50, 500, True);
  
  _deploy->show();
  
  if (side == PortSide)
    strcpy(namePtr, PORT_SA_STOW_DM);
  else
    strcpy(namePtr, STBD_SA_STOW_DM);

  _stow = new MomentaryPowerSwitch("stow", mgr2, itemName, "Stow",
				   100, 50, 500, True);
  
  _stow->show();

  XtManageChild(mgr2);
  

  label = XtVaCreateManagedWidget("positionLabel", xmLabelWidgetClass, mgr2,
				  NULL);
  
  _position = new DynamicLabel("position", mgr2);
  _position->show();
  
  XtManageChild(mgr2);

  mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, mgr,
		     XmNnumColumns, 2,
		     XmNpacking, XmPACK_COLUMN,
		     XmNorientation, XmHORIZONTAL,
		     NULL);

  unsigned firstValveNo;
  unsigned nValves;
  
  if (side == PortSide)
  {
    firstValveNo = 1;
    nValves = 4;
  }
  else
  {
    firstValveNo = 5;
    nValves = 3;
  }
  
  char prefix[MaxDmNameLen];
  DmObject::buildPrefix(prefix, platformName, MidwaterAppName, 0);

  valves = new ValveSelector("valves", mgr2, 
			     nValves,
			     firstValveNo,
			     prefix,
			     True);
  valves->show();
  
  XtManageChild(mgr2);
  
  XtManageChild(mgr);


  if (side == SwingArm::PortSide)
  {
    _dmPosition = dmItems->portSwingArmPosition;
  }
  else
  {
    _dmPosition = dmItems->stbdSwingArmPosition;
  }

  if (addDmObject(_dmPosition, DmConsumeFlag) == -1)
    return;

  if (setConsumePeriod(Aperiodic) == -1)
    return;

  _position->setText("         ");
  
  updateGui();
}


SwingArm::~SwingArm()
{
  delete _position;
  delete valves;
}


void SwingArm::updateGui(DM_Item)
{
  DM_Time t;
  Errno errno;
  char buf[errorMsgSize];
  Flt32 position;
  
  if ((errno = _dmPosition->read(&position, &t)) != SUCCESS)
  {
    sprintDmError(errno, "SwingArm::updateGui()", buf);
    setError(buf);
    return;
  }

  sprintf(buf, "%.0f", position);
  _position->setText(buf);
}



SwingArms::SwingArms(const char *name, Widget parent, MidwaterDm *dmItems,
		     const char *platformName)
{
  _baseWidget = XtVaCreateWidget(name, xmFormWidgetClass, parent,
				 NULL);
  
  installDestroyHandler();
  
  Widget label = 
    XtVaCreateManagedWidget("label", xmLabelWidgetClass, _baseWidget,
			    XmNtopAttachment, XmATTACH_FORM,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);
  
  portSwingArm = new SwingArm("portSwingArm", _baseWidget, 
			       SwingArm::PortSide, dmItems, platformName);

  XtVaSetValues(portSwingArm->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, label,
		NULL);
  
  portSwingArm->show();

  stbdSwingArm = new SwingArm("stbdSwingArm", _baseWidget,
			       SwingArm::StbdSide, dmItems, platformName);

  XtVaSetValues(stbdSwingArm->baseWidget(),
		XmNleftAttachment, XmATTACH_WIDGET,
		XmNleftWidget, portSwingArm->baseWidget(),
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, label,
		NULL);

  stbdSwingArm->show();

}



SwingArms::~SwingArms()
{
}


MidwaterPower::MidwaterPower(const char *name, Widget parent,
			     MidwaterGui *midwaterGui, 
			     const char *platformName)
{
  _baseWidget = XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
				XmNorientation, XmVERTICAL, NULL);
  
  installDestroyHandler();

  _midwaterGui = midwaterGui;
  
  Widget label = 
    XtVaCreateManagedWidget("powerLabel", xmLabelWidgetClass, _baseWidget, 
			    NULL);
  
  Widget mgr2 = 
    XtVaCreateWidget("mgr2", xmRowColumnWidgetClass, _baseWidget,
		     XmNorientation, XmHORIZONTAL, NULL);
  
  char itemName[MaxDmNameLen];
  DmObject::buildPrefix(itemName, platformName, PowerName, 0);

  char *namePtr = itemName + strlen(itemName);
  
  strcpy(namePtr, SA_POT_EXCITE_DM);
  
  armPositionSensor = 
    new PowerSwitchGui("armPositionSensor", mgr2, itemName,
		       "ArmPos Sensor", 100, 50, 500, True);
  
  armPositionSensor->addCallback(PowerSwitchGui::statusChangeCallback, this,
				 (VkCallbackMethod )
				 &MidwaterPower::statusCallback);
  
  armPositionSensor->show();

  strcpy(namePtr, SS_INDEX_EXCITE_DM);

  indexSensor = 
    new PowerSwitchGui("indexSensor", mgr2, itemName,
		       "Index Sensor", 100, 50, 500, True);
  
  indexSensor->addCallback(PowerSwitchGui::statusChangeCallback, this,
			   (VkCallbackMethod )
			   &MidwaterPower::statusCallback);
  
  indexSensor->show();

  strcpy(namePtr, TUNGSTEN_LAMP_DM);
  
  incandLight = new PowerSwitchGui("incandLight", mgr2,
				    itemName,
				    "Incand Light", 100, 50, 500, True);
  
  incandLight->show();

  strcpy(namePtr, SA_MOTOR_DM);
  
  arm = new PowerSwitchGui("arm", mgr2,
			   itemName,
			   "Swing-Arms", 100, 50, 500, True);
  
  arm->show();

  strcpy(namePtr, SS_PUMP_POWER_DM);
  
  pump = 
    new PowerSwitchGui("pump", mgr2, itemName,
		       "SS Pump", 100, 50, 500, True);
  
  pump->addCallback(PowerSwitchGui::statusChangeCallback, this,
		    (VkCallbackMethod )&MidwaterPower::statusCallback);

  pump->show();

  strcpy(namePtr, CAMERA_DM);
  
  pencilCamera = 
    new PowerSwitchGui("pencilCamera", mgr2, itemName,
		       "Camera", 100, 50, 500, True);

  pencilCamera->show();

  strcpy(namePtr, ACM_DM);
  
  acm = 
    new PowerSwitchGui("acm", mgr2, itemName,
		       "ACM", 100, 50, 500, True);

  acm->show();

  XtManageChild(mgr2);
}


MidwaterPower::~MidwaterPower()
{
  delete pump;
  delete incandLight;
  delete armPositionSensor;
  delete indexSensor;
  delete pencilCamera;
  delete acm;
}


void MidwaterPower::statusCallback(VkCallbackObject *obj,
				   void *clientData,
				   void *callData)
{
  Boolean debug = ((TiburonApp *)theApplication)->debug();
  
  dprintf(stderr, "MidwaterGui::powerSwitchCallback()\n");

  switchStatus status = (switchStatus )callData;

  if (obj == pump)
  {
    dprintf(stderr, "MidwaterGui::powerSwitchCallback() - pump status\n");

    switch (status)
    {
      case SWITCH_ON:
      case SWITCH_ON_CASCADE:
      _midwaterGui->suctionSampler->pump->setSensitive(True);
      break;
      
      default:
      _midwaterGui->suctionSampler->pump->setSensitive(False);
    }
  }
  else if (obj == armPositionSensor)
  {
    dprintf(stderr, "MidwaterGui::powerSwitchCallback() - exciter status\n");
  }
}



MidwaterGui::MidwaterGui(const char *name, Widget parent, 
			 const char *platformName)
{
  _baseWidget = XtVaCreateWidget(name, xmFormWidgetClass, parent, NULL);
  
  installDestroyHandler();

  _dmItems = new MidwaterDm(platformName);

  Widget label, title;

  title = 
    XtVaCreateManagedWidget("midwaterLabel", xmLabelWidgetClass, _baseWidget,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNrightAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);


  label = 
    XtVaCreateManagedWidget("hydraulicLabel", xmLabelWidgetClass, _baseWidget,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, title,
			    NULL);
  
  hydraulicSelect = new HydraulicSelect("hydraulicSelect", _baseWidget);
  XtVaSetValues(hydraulicSelect->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, label,
		NULL);
  
  hydraulicSelect->show();
  
  Widget powerFrame, armFrame, ssFrame;
  
  powerFrame =
    XtVaCreateManagedWidget("powerFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, hydraulicSelect->baseWidget(),
			    XmNrightAttachment, XmATTACH_FORM,
			    NULL);

  power = new MidwaterPower("power", powerFrame, this, platformName);
  power->show();
  
  armFrame =
    XtVaCreateManagedWidget("armFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, powerFrame,
			    XmNrightAttachment, XmATTACH_FORM,
			    NULL);
  
  swingArms = new SwingArms("swingArms", armFrame, _dmItems, platformName);
  swingArms->show();

  // Build array of ValveControls to use in ValveSwitchMap
  int nValves = 
    swingArms->portSwingArm->valves->nValves() + 
      swingArms->stbdSwingArm->valves->nValves();
  
  if ((_valveControl = 
       (ValveControl **)malloc(nValves * sizeof(ValveControl *))) == NULL)
  {
    fprintf(stderr, 
	    "MidwaterGui::MidwaterGui() - malloc of _valveControl failed\n");
    exit(1);
  }
  
  int j = 0;
  for (int i = 0 ; i < swingArms->portSwingArm->valves->nValves(); i++)
    _valveControl[j++] = swingArms->portSwingArm->valves->valve[i];
  
  for (int i = 0 ; i < swingArms->stbdSwingArm->valves->nValves(); i++)
    _valveControl[j++] = swingArms->stbdSwingArm->valves->valve[i];

  char itemName[MaxDmNameLen];
  
  DmObject::buildName(itemName, platformName, MidwaterAppName, 
		      MappedValveName, 0);
  
  _switchMap = new ValveSwitchMap("switchMap", _baseWidget, 2,
				  itemName,
				  nValves,
				  _valveControl);
  
  XtVaSetValues(_switchMap->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, armFrame,
		XmNrightAttachment, XmATTACH_FORM,
		NULL);

  _switchMap->show();


  ssFrame =
    XtVaCreateManagedWidget("ssFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _switchMap->baseWidget(),
			    NULL);
  
  suctionSampler = new SuctionSampler("suctionSampler", ssFrame, 
				      MidwaterAppName,
				      _dmItems->ssAutoIndex,
				      _dmItems->ssIndexSense,
				      _dmItems->ssJarNumber,
				      _dmItems->ssPumpSpeed,
				      _dmItems->ssPumpDirection);
  suctionSampler->show();
}


MidwaterGui::~MidwaterGui()
{
  delete hydraulicSelect;
  delete power;
  delete swingArms;
  delete suctionSampler;
  delete _switchMap;
  free((void *)_valveControl);
}





