#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Vk/VkErrorDialog.h>
#include "MonitoredValue.h"
#include "TiburonApp.h"
#include "ExternalApp.h"
#include "DmInfoWindow.h"

MonitoredValue::MonitoredValue(const char *name, Widget parent)
{
  _baseWidget = XtVaCreateWidget(name, xmRowColumnWidgetClass, parent,
				 XmNorientation, XmHORIZONTAL,
				 NULL);
  
  installDestroyHandler();

  ((TiburonApp *)theApplication)->priority1Colors(&_errorFg, &_errorBg);
  
  _label = 
    XtVaCreateManagedWidget("monitorLabel", xmLabelWidgetClass, _baseWidget,
			    NULL);
  
  _mgr = XtVaCreateWidget("mgr", xmFormWidgetClass, _baseWidget, NULL);
  
  _errorLabel = 
    XtVaCreateManagedWidget("errorLabel", xmLabelWidgetClass, _mgr,
			    XmNforeground, _errorFg, 
			    XmNbackground, _errorBg,
			    XmNleftAttachment, XmATTACH_FORM,
			    XmNrightAttachment, XmATTACH_FORM,
			    XmNtopAttachment, XmATTACH_FORM,
			    XmNbottomAttachment, XmATTACH_FORM,
			    NULL);

  XtSetMappedWhenManaged(_errorLabel, False);

  _value = NULL;
  _plotButton = NULL;
  _dmObject = NULL;

}



MonitoredValue::~MonitoredValue()
{
  delete _value;
  delete _dmObject;
}



void MonitoredValue::setErrorLabel(char *errorBuf)
{
  Boolean debug = False;
  
  clear();
  dprintf(stderr, "setErrorLabel(): \"%s\"\n", errorBuf); 
  
  XmString xmstr = XmStringCreateSimple(errorBuf);

  XtVaSetValues(_errorLabel, XmNlabelString, xmstr, NULL);
  XtMapWidget(_errorLabel);
  
  XtManageChild(_mgr);
  XtManageChild(_baseWidget);
  
  XmStringFree(xmstr);

  return;
}



int MonitoredValue::createValue(GraduatedAlarm *alarm)
{
  Boolean debug = False;
  
  clear();

  DM_Item dmItem;
  Boolean error = False;
  char errorBuf[errorMsgSize];
  
  const char *itemName = alarm->monitoredItem();

  DM_Type type;
  if (!findItem(itemName, &type))
  {
    dprintf(stderr, "createValue() - couldn't find item:\n%s\n", itemName);
    return -1;
  }
  
  const int period = 500;
  
  AlarmedText *alarmedText = NULL;
  
  char format[100];
  
  switch (type)
  {
    case DM_INT16:
    _dmObject = new DmInt16Object(itemName);
    sprintf(format, "%s = %%-3.0f", itemName);
    
    alarmedText = new AlarmedInt16Text("alarmedText", _mgr, format,
				       (DmInt16Object *)_dmObject, 
				       period,
				       alarm, 
				       Dynamic);
    break;

    case DM_NAT16:
    _dmObject = new DmNat16Object(itemName);
    sprintf(format, "%s = %%-3.0f", itemName);    

    alarmedText = new AlarmedNat16Text("alarmedText", _mgr, format,
				       (DmNat16Object *)_dmObject, 
				       period,
				       alarm, 
				       Dynamic);
    break;
    
    case DM_FLT32:
    
    _dmObject = new DmFlt32Object(itemName);
    sprintf(format, "%s = %%-3.4f", itemName);    

    alarmedText = new AlarmedFlt32Text("alarmedText", _mgr, format,
				       (DmFlt32Object *)_dmObject, 
				       period,
				       alarm, 
				       Dynamic);
    break;


    default:
    char errorBuf[errorMsgSize];
    sprintf(errorBuf, "\"%s\": type %d unsupported", itemName, type);
    setErrorLabel(errorBuf);
    return -1;
  }

  _value = alarmedText;

  if (alarmedText)
  {
    XtVaSetValues(alarmedText->baseWidget(),
		  XmNleftAttachment, XmATTACH_FORM,
		  XmNtopAttachment, XmATTACH_FORM,
		  XmNbottomAttachment, XmATTACH_FORM,
		  NULL);
  
    dprintf(stderr, "createValue() - created alarmedText\n");

    alarmedText->realize();
    alarmedText->show();

    _plotButton = 
      XtVaCreateManagedWidget("plotButton", xmPushButtonWidgetClass, _mgr,
			      XmNleftAttachment, XmATTACH_WIDGET,
			      XmNleftWidget, alarmedText->baseWidget(),
			      XmNtopAttachment, XmATTACH_FORM,
			      XmNbottomAttachment, XmATTACH_FORM,
			      XmNrightAttachment, XmATTACH_FORM,
			      NULL);
    
    XtAddCallback(_plotButton, XmNactivateCallback, 
		  &MonitoredValue::plotCallback,
		  (XtPointer )_dmObject->getName());
			    
  }
  
  XtManageChild(_mgr);


  // TEST TEST TEST
  Dimension width, height;
  XtVaGetValues(_mgr, XmNwidth, &width, XmNheight, &height, NULL);
  dprintf(stderr, "createValue() - mgr width=%d, height=%d\n",
	  width, height);

  XtManageChild(_baseWidget);
  
  return 0;
}


void MonitoredValue::clear()
{
  if (_value)
  {
    delete _value;
    _value = NULL;
  }

  if (_plotButton)
  {
    XtDestroyWidget(_plotButton);
    _plotButton = NULL;
  }
  
  if (_dmObject)
  {
    delete _dmObject;
    _dmObject = NULL;
  }
}


DM_Item MonitoredValue::findItem(const char *itemName, DM_Type *type)
{
  DM_Item dmItem = NULL;
  Boolean error = False;
  char errorBuf[errorMsgSize];

  if (!itemName)
  {
    strcpy(errorBuf, "Not specified");
    error = True;
  }
  else
  {
    dmItem = dm_lookup((char *)itemName, 0);
    if (!dmItem)
    {
      sprintf(errorBuf, "\"%s\" not found", itemName);
      error = True;
    }
  }

  if (error)
  {
    setErrorLabel(errorBuf);
    return NULL;
  }

  DmItemSts status;
  if (dm_item_status(dmItem, &status) != SUCCESS)
  {
    theErrorDialog->postAndWait("ValueBox::findItem() - "
				"dm_item_status() failed\n");
    
    return NULL;
  }

  *type = status.is_type;

  dm_item_status_free(&status);
  
  return dmItem;
}


void MonitoredValue::plotCallback(Widget w,
				  XtPointer clientData,
				  XtPointer callData)
{
  Boolean debug = False;
  dprintf(stderr, "MonitoredValue::plotCallback()\n");

  char *itemName = (const char *)clientData;

  DmInfoWindow *dmInfoWindow = 
    new DmInfoWindow("dmInfoWindow", itemName, True);
  
  dmInfoWindow->show();
  
}
