#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/Frame.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Vk/VkErrorDialog.h>
#include "Regen.h"
#include "TiburonApp.h"
#include "TableForm.h"
#include "regenDm.h"

Regen::Regen(const char *name, Widget parent, int period, 
	     const char *dmPrefix)
  : VkComponent(name)
{
  _minVoltage = 0;
  _maxVoltage = 0;
  _heater1Temp = 0;
  _heater2Temp = 0;
  _openHeater = 0;
  _dutyCycle1 = 0;
  _dutyCycle2 = 0;
  _volts = 0;
  _heatsinkTemp = 0;

  _baseWidget = 
    XtVaCreateWidget(name, xmRowColumnWidgetClass, parent, 
		     XmNorientation, XmVERTICAL,
		     NULL);
  
  installDestroyHandler();
  
  Widget mgr;
  mgr = XtVaCreateWidget("mgr", xmRowColumnWidgetClass, _baseWidget,
			 XmNorientation, XmHORIZONTAL,
			 NULL);
  
  TiburonApp *app = (TiburonApp *)theApplication;

  char alarmName[MaxDmNameLen];
  strcpy(alarmName, dmPrefix);
  char *alarmNamePtr = alarmName + strlen(alarmName);
  
  char itemName[MaxDmNameLen];
  strcpy(itemName, dmPrefix);
  char *namePtr = itemName + strlen(itemName);

  strcpy(namePtr, REGEN_BUS_VOLTAGE_DM);

  _volts =
    new DmInt16BarGraph("volts", mgr, itemName, period, NULL,
			150, 350);

  _volts->show();

  strcpy(namePtr, REGEN_DUTY_CYCLE1_DM);

  // Note that we use a single duty cycle alarm for both cycles 1 and 2
  strcpy(alarmNamePtr, REGEN_DUTY_CYCLE_ALARM_DM);
  
  _dutyCycle1 = 
    new DmInt16BarGraph("dutyCycle1", mgr, itemName, period, alarmName,
			0, 100);
  _dutyCycle1->show();

  strcpy(namePtr, REGEN_DUTY_CYCLE2_DM);

  _dutyCycle2 = 
    new DmInt16BarGraph("dutyCycle2", mgr, itemName, period, alarmName,
			0, 100);
  _dutyCycle2->show();


  strcpy(namePtr, REGEN_HEATSINK_TEMP_DM);
  strcpy(alarmNamePtr, REGEN_HEATSINK_TEMP_ALARM_DM);
  
  _heatsinkTemp = 
    new DmInt16BarGraph("heatsinkTemp", mgr, itemName, period, alarmName,
			0, 100);
  _heatsinkTemp->show();

  XtManageChild(mgr);

  strcpy(namePtr, REGEN_MIN_BUS_VOLTAGE_DM);
  _dmMinVoltage = new DmInt16Object(itemName);

  strcpy(alarmNamePtr, REGEN_MIN_VOLTAGE_ALARM_DM);
  Alarm *minVoltageAlarm = app->systemAlarms->find(alarmName);
  
  strcpy(namePtr, REGEN_MAX_BUS_VOLTAGE_DM);
  _dmMaxVoltage = new DmInt16Object(itemName);

  strcpy(alarmNamePtr, REGEN_MAX_VOLT_ALARM_DM);
  Alarm *maxVoltageAlarm = app->systemAlarms->find(alarmName);

  strcpy(namePtr, REGEN_HEATER1_TEMP_DM);
  _dmHeater1Temp = new DmInt16Object(itemName);

  strcpy(alarmNamePtr, REGEN_HEATER1_TEMP_ALARM_DM);
  Alarm *heater1TempAlarm = app->systemAlarms->find(alarmName);

  strcpy(namePtr, REGEN_HEATER2_TEMP_DM);
  _dmHeater2Temp = new DmInt16Object(itemName);

  strcpy(alarmNamePtr, REGEN_HEATER2_TEMP_ALARM_DM);
  Alarm *heater2TempAlarm = app->systemAlarms->find(alarmName);

  strcpy(alarmNamePtr, REGEN_OPEN_HEATER_ALARM_DM);
  Alarm *openHeaterAlarm = app->systemAlarms->find(alarmName);
  
  TableRowForm *row;
  Widget label;
  
  row = new TableRowForm("row", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("minVoltageLabel", xmLabelWidgetClass, 
			    row->baseWidget(), NULL);
  
  row->append(label);
  
  _minVoltage = new AlarmedInt16Text("minVoltage", row->baseWidget(),
					"%-3.0f", _dmMinVoltage, period, 
					minVoltageAlarm, Dynamic, 1.); 

  row->append(_minVoltage);
  row->show();

  row = new TableRowForm("row", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("maxVoltageLabel", xmLabelWidgetClass, 
			    row->baseWidget(), NULL);
  
  row->append(label);
  
  _maxVoltage = new AlarmedInt16Text("maxVoltage", row->baseWidget(),
					"%-3.0f", _dmMaxVoltage, period, 
					maxVoltageAlarm, Dynamic, 1.); 

  row->append(_maxVoltage);
  row->show();
  
  row = new TableRowForm("row", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("heater1TempLabel", xmLabelWidgetClass, 
			    row->baseWidget(), NULL);
  
  row->append(label);
  
  _heater1Temp = new AlarmedInt16Text("heater1Temp", row->baseWidget(),
				      "%-3.0f", _dmHeater1Temp, period, 
				      heater1TempAlarm, Dynamic, 1.); 

  row->append(_heater1Temp);
  row->show();

  row = new TableRowForm("row", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("heater2TempLabel", xmLabelWidgetClass, 
			    row->baseWidget(), NULL);
  
  row->append(label);
  
  _heater2Temp = new AlarmedInt16Text("heater2Temp", row->baseWidget(),
				      "%-3.0f", _dmHeater2Temp, period, 
				      heater2TempAlarm, Dynamic, 1.); 

  row->append(_heater2Temp);
  row->show();

  row = new TableRowForm("row", _baseWidget, 2);

  label = 
    XtVaCreateManagedWidget("openHeaterLabel", xmLabelWidgetClass, 
			    row->baseWidget(), NULL);
  
  row->append(label);
  
  _openHeater = new AlarmText("heater1Temp", row->baseWidget(),
			      openHeaterAlarm, "%s");

  row->append(_openHeater);
  row->show();

  row = new TableRowForm("row", _baseWidget, 2);

  Widget button = 
    XtVaCreateManagedWidget("resetMinMax", xmPushButtonWidgetClass, 
			    row->baseWidget(), NULL);

  row->append(button);
  row->show();
  
  XtAddCallback(button, XmNactivateCallback, &Regen::resetCallback, this);
  
  strcpy(namePtr, REGEN_RESET_MIN_MAX_DM);
  _dmResetMinMax = new DmEmptyObject(itemName);
}


Regen::~Regen()
{
  delete _minVoltage;
  delete _maxVoltage;
  delete _heater1Temp;
  delete _heater2Temp;
  delete _openHeater;
  delete _dutyCycle1;
  delete _dutyCycle2;
  delete _volts;
  delete _heatsinkTemp;
}


void Regen::sendReset()
{
  if (_dmResetMinMax->startProvide(DM_ASYNC) == -1)
  {
    theErrorDialog->postAndWait("Regen::sendReset(); startProvide() failed");
    return;
  }

  DM_Time t;
  t.tv_sec = time(NULL);
  t.tv_usec = 0;

  Errno errno;
  char errorBuf[errorMsgSize];
  
  if ((errno = _dmResetMinMax->write(&t)) != SUCCESS)
  {
    sprintDmError(errno, "Regen::sendReset()", errorBuf);
    theErrorDialog->postAndWait(errorBuf);
  }

  _dmResetMinMax->stopProvide();
}


void Regen::resetCallback(Widget w, 
			  XtPointer clientData, XtPointer callData)
{
  Regen *obj = (Regen *)clientData;
  obj->sendReset();
}


RegenPage::RegenPage(const char *name, Widget parent)
{
  _pwrA = 0;
  _pwrB = 0;

  _baseWidget = 
    XtVaCreateWidget(name, xmRowColumnWidgetClass, parent, 
		     XmNorientation, XmHORIZONTAL, 
		     NULL);
  
  installDestroyHandler();
  
  Widget frame;
  Widget mgr;
  Widget label;
  
  frame = 
    XtVaCreateManagedWidget("frame", xmFrameWidgetClass, _baseWidget, NULL);
  
  mgr = XtVaCreateWidget("mgr", xmFormWidgetClass, frame, NULL);
  
  label = 
    XtVaCreateManagedWidget("regenPwrALabel", xmLabelWidgetClass, mgr,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);

  _pwrA = new Regen("regenPwrA", mgr, 500, PWR_IBC_A_DM_PREFIX);

  XtVaSetValues(_pwrA->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, label,
		NULL);

  _pwrA->show();
  
  XtManageChild(mgr);


  frame = 
    XtVaCreateManagedWidget("frame", xmFrameWidgetClass, _baseWidget, NULL);
  
  mgr = XtVaCreateWidget("mgr", xmFormWidgetClass, frame, NULL);
  
  label = 
    XtVaCreateManagedWidget("regenPwrBLabel", xmLabelWidgetClass, mgr,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_FORM,
			    NULL);

  _pwrB = new Regen("regenPwrB", mgr, 500, PWR_IBC_B_DM_PREFIX);

  XtVaSetValues(_pwrB->baseWidget(),
		XmNleftAttachment, XmATTACH_FORM,
		XmNtopAttachment, XmATTACH_WIDGET,
		XmNtopWidget, label,
		NULL);

  _pwrB->show();
  
  XtManageChild(mgr);
  
} 


RegenPage::~RegenPage()
{
  delete _pwrA;
  delete _pwrB;
}
