#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Vk/VkErrorDialog.h>
#include "Predive.h"
#include "sensorDcon.h"
#include "sensorsDm.h"
#include "controlDM.h"
#include "vmeIbc.h"
#include "DmErrno.h"

Predive::Predive(const char *name, Widget parent)
  : VkComponent(name)
{
  _baseWidget = XtCreateWidget(_name, xmFormWidgetClass, parent, NULL, 0);
  installDestroyHandler();

  Widget label;
  
  const int column1 = 1;
  const int column2 = 30;
  const int topOffset = 20;
  
  label = XtVaCreateManagedWidget("diveNoLabel", 
				  xmLabelWidgetClass, _baseWidget,
				  XmNtopAttachment, XmATTACH_FORM,
				  XmNleftAttachment, column1,
				  NULL);
  
  _diveNo = new DmStringText("diveNo", _baseWidget, 
			     TIBURON_DIVENUMBER_DM,
			     TIBURON_DIVENUMBER_LEN, 
			     Aperiodic);

  XtVaSetValues(_diveNo->baseWidget(),
		XmNtopAttachment, XmATTACH_FORM,
		XmNleftAttachment, XmATTACH_POSITION,
		XmNleftPosition, column2,
		NULL);
  
  _diveNo->show();
  
  label = XtVaCreateManagedWidget("pressureOffsetLabel", 
				  xmLabelWidgetClass, _baseWidget,
				  XmNtopAttachment, XmATTACH_WIDGET,
				  XmNtopWidget, _diveNo->baseWidget(),
				  XmNtopOffset, topOffset,
				  XmNleftAttachment, column1,
				  XmNtopOffset, topOffset,
				  NULL);

  _depthOffset = new DmFlt64Text("depthOffset", _baseWidget,
				 SENSOR_IBC_DM_PREFIX 
				 PRESSURE_SENSOR_OFFSET_DM,
				 Aperiodic);

  XtVaSetValues(_depthOffset->baseWidget(),
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, _diveNo->baseWidget(),
		XmNtopOffset, topOffset,
		XmNleftAttachment, XmATTACH_POSITION,
		XmNleftPosition, column2,
		NULL);

  _depthOffset->show();

  Widget button = 
    XtVaCreateManagedWidget("calibrateDepthOffset",
			    xmPushButtonWidgetClass, _baseWidget,
			    XmNleftAttachment, XmATTACH_WIDGET,
			    XmNleftWidget, _depthOffset->baseWidget(),
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, _diveNo->baseWidget(),
			    XmNtopOffset, topOffset,
			    NULL);
  
  XtAddCallback(button, XmNactivateCallback, 
		&Predive::calibrateDepthOffsetCallback,
		(XtPointer )this);

  label = XtVaCreateManagedWidget("compassOffsetLabel",
				  xmLabelWidgetClass, _baseWidget,
				  XmNtopAttachment, XmATTACH_WIDGET,
				  XmNtopWidget, _depthOffset->baseWidget(),
				  XmNtopOffset, topOffset,
				  XmNleftAttachment, column1,
				  NULL);
				  
  _compassOffset = new DmFlt32Text("compassOffset", _baseWidget,
				   SENSOR_DM_PREFIX COMPASS_MAG_VARIATION_DM,
				   Aperiodic);
  
  XtVaSetValues(_compassOffset->baseWidget(),
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, _depthOffset->baseWidget(),
		XmNtopOffset, topOffset,
		XmNleftAttachment, XmATTACH_POSITION,
		XmNleftPosition, column2,
		NULL);

  _compassOffset->show();
  
}


Predive::~Predive()
{
}


void Predive::calibrateDepthOffset()
{

  char itemName[MaxDmNameLen];
  char errorBuf[errorMsgSize];
  
  strcpy(itemName, SENSOR_IBC_DM_PREFIX);
  strcat(itemName, PRESSURE_SENSOR_DM);

  DmFlt64Object *dmDepth = new DmFlt64Object(itemName);
  if (dmDepth->error())
  {
    dmDepth->errorMsg(errorBuf);
    theErrorDialog->post(errorBuf);
    delete dmDepth;
    return;
  }

  Flt64 depth;
  DM_Time t;
  Errno errno;
  if ((errno = dmDepth->startConsume(100, NULL)) != SUCCESS)
  {
    sprintDmError(errno, 
		  "Predive::calibrateDepthOffset() - startConsume() failed",
		  errorBuf);
    
    theErrorDialog->post(errorBuf);
    delete dmDepth;
    return;
  }
  
  errno = dmDepth->read(&depth, &t);
  if (errno != SUCCESS)
  {
    sprintDmError(errno, 
		  "Predive::calibrateDepthOffset() - read of depth failed",
		  errorBuf);
    
    theErrorDialog->post(errorBuf);
    delete dmDepth;
    return;
  }
  char buf[100];
  sprintf(buf, "%.1f", depth);
  _depthOffset->text->set(buf);
  delete dmDepth;
}


void Predive::calibrateDepthOffsetCallback(Widget w, 
					   XtPointer clientData,
					   XtPointer callData)
{
  Predive *obj = (Predive *)clientData;
  obj->calibrateDepthOffset();
}


int Predive::writeValues()
{
  char errorBuf[errorMsgSize];
  Errno errno;
  
  if (!_diveNo->validInput(errorBuf))
  {
    strcat(errorBuf, "Dive info not written");
    theErrorDialog->post(errorBuf);
  }
  else if ((errno = _diveNo->writeValue()) != SUCCESS)
  {
    sprintDmError(errno, "Failed writing dive info", errorBuf); 
  }

  if (!_depthOffset->validInput(errorBuf))
  {
    strcat(errorBuf, "  Depth offset not written");
    theErrorDialog->post(errorBuf);
  }
  else if ((errno = _depthOffset->writeValue()) != SUCCESS)
  {
    sprintDmError(errno, "Failed writing depth offset value", errorBuf); 
  }
  
  if (!_compassOffset->validInput(errorBuf))
  {
    strcat(errorBuf, "  Compass offset not written");
    theErrorDialog->post(errorBuf);
  }
  else if ((errno = _compassOffset->writeValue()) != SUCCESS)
  {
    sprintDmError(errno, "Failed writing compass offset value", errorBuf); 
  }

  return 0;
}

