#include <Xm/RowColumn.h>
#include <Xm/Form.h>
#include <Xm/PushB.h>
#include <Xm/Label.h>
#include <Xm/Frame.h>
#include <Xm/ScrolledW.h>
#include <Vk/VkApp.h>
#include <Vk/VkErrorDialog.h>
#include "MicroSelect.h"
#include "TiburonApp.h"

#define dprintf if (debug) fprintf

const int MicroSelect::_dividerPosition = 35;


MicroSelect::MicroSelect(const char *name, Widget parent)
{
  _microGui = 0;
 
  _baseWidget = XtVaCreateWidget(name, xmFormWidgetClass, parent, 
				 XmNresizePolicy, XmRESIZE_GROW,
				 NULL);
  installDestroyHandler();

  Widget ibcFrame, motorFrame, threeByFiveFrame;
  Widget mgr;
  Widget label;

  _selectedMicro = 
    XtVaCreateManagedWidget("selectedMicro", xmLabelWidgetClass, 
			    _baseWidget,
			    XmNtopAttachment, XmATTACH_FORM,
			    XmNleftAttachment, XmATTACH_POSITION,
			    XmNleftPosition, _dividerPosition,
			    NULL);
    
  ibcFrame = 
    XtVaCreateManagedWidget("ibcFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNtopAttachment, XmATTACH_FORM,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);
  
  mgr = XtVaCreateWidget("mgr", xmRowColumnWidgetClass, ibcFrame, NULL);

  label = 
    XtVaCreateManagedWidget("ibcLabel", xmLabelWidgetClass, mgr, NULL);

  _ibcMgr = 
    XtVaCreateWidget("ibcMgr", xmRowColumnWidgetClass, mgr,
		     XmNnumColumns, 3,
		     XmNpacking, XmPACK_COLUMN,
		     XmNorientation, XmVERTICAL,
		     NULL);

  XtManageChild(_ibcMgr);
  XtManageChild(mgr);

  motorFrame = 
    XtVaCreateManagedWidget("motorFrame", xmFrameWidgetClass, _baseWidget, 
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, ibcFrame,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);
  
  mgr = XtVaCreateWidget("mgr", xmRowColumnWidgetClass, motorFrame, NULL);

  label = 
    XtVaCreateManagedWidget("motorLabel", xmLabelWidgetClass, mgr, NULL);

  _motorMgr = 
    XtVaCreateWidget("motorMgr", xmRowColumnWidgetClass, mgr,
		     XmNnumColumns, 3,
		     XmNpacking, XmPACK_COLUMN,
		     XmNorientation, XmVERTICAL,
		     NULL);

  XtManageChild(_motorMgr);
  XtManageChild(mgr);
  
  threeByFiveFrame = 
    XtVaCreateManagedWidget("threeByFiveFrame", xmFrameWidgetClass, 
			    _baseWidget, 
			    XmNtopAttachment, XmATTACH_WIDGET,
			    XmNtopWidget, motorFrame,
			    XmNleftAttachment, XmATTACH_FORM,
			    NULL);
  
  mgr = XtVaCreateWidget("mgr", xmRowColumnWidgetClass, threeByFiveFrame, NULL);

  label = 
    XtVaCreateManagedWidget("threeByFiveLabel", xmLabelWidgetClass, mgr, NULL);

  _threeByFiveMgr = 
    XtVaCreateWidget("threeByFiveMgr", xmRowColumnWidgetClass, mgr,
		     XmNnumColumns, 3,
		     XmNpacking, XmPACK_COLUMN,
		     XmNorientation, XmVERTICAL,
		     NULL);

  XtManageChild(_threeByFiveMgr);
  XtManageChild(mgr);

  _scrolledWindow = NULL;
  _microGui = NULL;
  
  _micros.clear();
  
  addButtons(((TiburonApp *)theApplication)->vehicleConfig->vehicleBase);
}


MicroSelect::~MicroSelect()
{
  delete _microGui;
}


void MicroSelect::addButtons(VehicleComponent *parent)
{
  VehicleComponent **child;
  SListIter<VehicleComponent *> children(parent->childList);

  while (child = children.next())
  {
    if ((*child)->isMicro())
    {
      Micro *micro = (Micro *)(*child);

      Widget mgr;
      switch (micro->type())
      {
	case VehicleComponent::IbcType:
	case VehicleComponent::DconType:
	mgr = _ibcMgr;
	break;
	
	case VehicleComponent::MotorMicroType:
	case VehicleComponent::SemiMotorMicroType:
	mgr = _motorMgr;
	break;
	
	case VehicleComponent::CameraMicroType:
	case VehicleComponent::PanTiltMicroType:
	case VehicleComponent::Sio32MicroType:
	case VehicleComponent::TelemMicroType:
	case VehicleComponent::PduMicroType:
	mgr = _threeByFiveMgr;
	break;
      }

      /* Create button widget with same name as micro. Callback gets this 
	 widget when user pushes button; therefore we also get micro name. */
      Widget button = 
	XtVaCreateManagedWidget(micro->name(), xmPushButtonWidgetClass, mgr,
				XmNrecomputeSize, False,
				NULL);

      XtAddCallback(button, XmNactivateCallback, 
		    &MicroSelect::buttonCallback,
		    (XtPointer )this);

      _micros.add(&micro);
    }

    addButtons(*child);
  }
}


void MicroSelect::buttonCallback(Widget w, 
				 XtPointer clientData, XtPointer callData)
{
  MicroSelect *obj = (MicroSelect *)clientData;
  obj->displaySelectedGui(w);
}


void MicroSelect::displaySelectedGui(Widget w)
{
  theApplication->busy();
  XFlush(theApplication->display());
  
  Boolean debug = False;
  Micro *micro;

  if (w == NULL)
  {
    // Just get first micro
    _micros.get(0, &micro);
  }
  else
  {
    char *microName = XtName(w);
    XmString xmstr;
    XtVaGetValues(w, XmNlabelString, &xmstr, NULL);
    XtVaSetValues(_selectedMicro, XmNlabelString, xmstr, NULL);
    
    // Look through array of micros, find matching name
    Boolean found = False;
    for (int i = 0; i < _micros.size(); i++)  
    {
      _micros.get(i, &micro);
      if (!strcmp(micro->name(), microName))
      {
	dprintf(stderr, "Selected micro \"%s\"\n", micro->name());
	found = True;
	break;
      }
    }
    if (!found)
    {
      fprintf(stderr, 
	      "MicroSelect::displaySelectedGui() - couldn't find micro "
	      "\"%s\"\n",
	      microName);
    
      return;
    }
  }
  
  if (_microGui)
    delete _microGui;

  if (_scrolledWindow)
    XtDestroyWidget(_scrolledWindow);

  _scrolledWindow = 
    XtVaCreateWidget("scrolledWindow", xmScrolledWindowWidgetClass,
		     _baseWidget,
		     XmNscrollingPolicy, XmAUTOMATIC,
		     XmNtopAttachment, XmATTACH_WIDGET,
		     XmNtopWidget, _selectedMicro,
		     XmNleftAttachment, XmATTACH_POSITION,
		     XmNleftPosition, _dividerPosition,
		     XmNrightAttachment, XmATTACH_FORM,
		     XmNbottomAttachment, XmATTACH_FORM,		
		     NULL);

  _workArea = 
    XtVaCreateWidget("workArea", xmRowColumnWidgetClass, _scrolledWindow,
		     NULL);
  
  _microGui = micro->gui(_workArea, 500);
  if (!_microGui)
  {
    theApplication->notBusy();
    return;
  }  

  if (_microGui->error())
  {
    char errorBuf[errorMsgSize];
    _microGui->errorMsg(errorBuf);

    delete _microGui;
    _microGui = NULL;

    theErrorDialog->postAndWait(errorBuf);
  }
  else
    _microGui->show();

  XtManageChild(_workArea);
  XtManageChild(_scrolledWindow);
  Dimension width, height;

  XtVaSetValues(_workArea, XmNwidth, 700, XmNresizeWidth, False, NULL);
  
  XtVaGetValues(_workArea, XmNwidth, &width, XmNheight, &height, NULL);
  dprintf(stderr, "workArea: width=%d, height=%d\n", width, height);
  XtVaGetValues(_scrolledWindow, XmNwidth, &width, XmNheight, &height, NULL);
  dprintf(stderr, "scrolledWindow: width=%d, height=%d\n", width, height);  
  XtVaSetValues(_scrolledWindow, XmNworkWindow, _workArea, NULL);
  theApplication->notBusy();
}



