#include <Interface.h>

Scatter *scatterptr;
SoTimerSensor *sensorptr;

Interface::Interface (Scatter *s, SoTimerSensor *sen) {
  scatterptr = s;
  sensorptr  = sen;

  initialDR  = 0.0;
  initialDM  = 0.0;
  initialPR  = 0.0;
  initialPM  = 0.0;
  initialNUM = 0;
}

void Interface::setInitial (float dr, float dm, float pr,
			    float pm, int num) {
  initialDR  = dr;
  initialDM  = dm;
  initialPR  = pr;
  initialPM  = pm;
  initialNUM = num;
}  

Widget Interface::makeGUI (Widget parent) {
  Arg args[20];
  int decimalPts = 2;
  int offset = 80;
  
  Widget controls = XtCreateWidget("Form", xmFormWidgetClass, parent,
				   NULL, 0);
  XtSetArg(args[0], XmNtopAttachment, XmATTACH_FORM);
  XtSetArg(args[1], XmNbottomAttachment, XmATTACH_FORM);
  XtSetArg(args[2], XmNrightAttachment, XmATTACH_FORM);
  XtSetArg(args[3], XmNleftAttachment, XmATTACH_POSITION);
  XtSetArg(args[4], XmNleftPosition, offset + 1);
  XtSetValues(controls, args, 5);

  XmString deflectorText = XmStringCreate("Deflector",
					  XmFONTLIST_DEFAULT_TAG);
  Widget deflectorLabel  = XtCreateWidget("Label", xmLabelWidgetClass,
					  controls, NULL, 0);
  XtSetArg(args[0], XmNlabelString, deflectorText);
  XtSetArg(args[1], XmNx, 2);
  XtSetArg(args[2], XmNy, 2);
  XtSetValues(deflectorLabel, args, 3);
  SoXt::show(deflectorLabel);

  XmString radiusText   = XmStringCreate("Radius", XmFONTLIST_DEFAULT_TAG);
  Widget defRadiusScale = XtCreateWidget("Scale", xmScaleWidgetClass,
					 controls, NULL, 0);
  XtSetArg(args[0], XmNtitleString, radiusText);
  XtSetArg(args[1], XmNx, 5);
  XtSetArg(args[2], XmNy, 25);
  XtSetArg(args[3], XmNorientation, XmHORIZONTAL);
  XtSetArg(args[4], XmNminimum, 0);
  XtSetArg(args[5], XmNmaximum, 300);
  XtSetArg(args[6], XmNdecimalPoints, decimalPts);
  XtSetArg(args[7], XmNshowValue, TRUE);
  XtSetArg(args[8], XmNscaleWidth, 137);
  XtSetArg(args[9], XmNvalue, (int)(initialDR * 100.0));
  XtSetValues(defRadiusScale, args, 10);
  XtAddCallback(defRadiusScale, XmNvalueChangedCallback,
                (XtCallbackProc) radiusDefCB, NULL);   
  SoXt::show(defRadiusScale);

  XmString massText   = XmStringCreate("Mass", XmFONTLIST_DEFAULT_TAG);
  Widget defMassScale = XtCreateWidget("Scale", xmScaleWidgetClass,
					 controls, NULL, 0);
  XtSetArg(args[0], XmNtitleString, massText);
  XtSetArg(args[1], XmNx, 5);
  XtSetArg(args[2], XmNy, 90);
  XtSetArg(args[3], XmNorientation, XmHORIZONTAL);
  XtSetArg(args[4], XmNminimum, 0);
  XtSetArg(args[5], XmNmaximum, 1000);
  XtSetArg(args[6], XmNshowValue, TRUE);
  XtSetArg(args[7], XmNscaleWidth, 137);
  XtSetArg(args[8], XmNvalue, (int)initialDM);
  XtSetValues(defMassScale, args, 9);
  XtAddCallback(defMassScale, XmNvalueChangedCallback,
                (XtCallbackProc) massDefCB, NULL);
  SoXt::show(defMassScale);

  Widget parSep = XtCreateWidget("Separator", xmSeparatorWidgetClass,
				 controls, NULL, 0);
  XtSetArg(args[0], XmNx, 0);
  XtSetArg(args[1], XmNy, 160);
  XtSetArg(args[2], XmNwidth, 125);
  XtSetArg(args[3], XmNheight, 3);
  XtSetValues(parSep, args, 4);
  SoXt::show(parSep);

  XmString particlesText = XmStringCreate("Particles",
					  XmFONTLIST_DEFAULT_TAG);
  Widget particlesLabel  = XtCreateWidget("Label", xmLabelWidgetClass,
					  controls, NULL, 0);
  XtSetArg(args[0], XmNlabelString, particlesText);
  XtSetArg(args[1], XmNx, 2);
  XtSetArg(args[2], XmNy, 165);
  XtSetValues(particlesLabel, args, 3);
  SoXt::show(particlesLabel);

  XmString parNumText = XmStringCreate("Number",
					  XmFONTLIST_DEFAULT_TAG);
  Widget parNumScale = XtCreateWidget("Scale", xmScaleWidgetClass,
					 controls, NULL, 0);
  XtSetArg(args[0], XmNtitleString, parNumText);
  XtSetArg(args[1], XmNx, 5);
  XtSetArg(args[2], XmNy, 185);
  XtSetArg(args[3], XmNorientation, XmHORIZONTAL);
  XtSetArg(args[4], XmNminimum, 0);
  XtSetArg(args[5], XmNmaximum, 1000);
  XtSetArg(args[6], XmNshowValue, TRUE);
  XtSetArg(args[7], XmNscaleWidth, 137);
  XtSetArg(args[8], XmNvalue, initialNUM);
  XtSetValues(parNumScale, args, 9);
  XtAddCallback(parNumScale, XmNvalueChangedCallback,
                (XtCallbackProc) numberCB, NULL);
  SoXt::show(parNumScale);

  Widget parRadiusScale = XtCreateWidget("Scale", xmScaleWidgetClass,
					 controls, NULL, 0);
  XtSetArg(args[0], XmNtitleString, radiusText);
  XtSetArg(args[1], XmNx, 5);
  XtSetArg(args[2], XmNy, 250);
  XtSetArg(args[3], XmNorientation, XmHORIZONTAL);
  XtSetArg(args[4], XmNminimum, 0);
  XtSetArg(args[5], XmNmaximum, 100);
  XtSetArg(args[6], XmNdecimalPoints, 2);
  XtSetArg(args[7], XmNshowValue, TRUE);
  XtSetArg(args[8], XmNscaleWidth, 137);
  XtSetArg(args[9], XmNvalue, (int)(initialPR * 100.0));
  XtSetValues(parRadiusScale, args, 10);
  XtAddCallback(parRadiusScale, XmNvalueChangedCallback,
                (XtCallbackProc) radiusParCB, NULL);
  SoXt::show(parRadiusScale);

  Widget parMassScale = XtCreateWidget("Scale", xmScaleWidgetClass,
					 controls, NULL, 0);
  XtSetArg(args[0], XmNtitleString, massText);
  XtSetArg(args[1], XmNx, 5);
  XtSetArg(args[2], XmNy, 315);
  XtSetArg(args[3], XmNorientation, XmHORIZONTAL);
  XtSetArg(args[4], XmNminimum, 0);
  XtSetArg(args[5], XmNmaximum, 1000);
  XtSetArg(args[6], XmNshowValue, TRUE);
  XtSetArg(args[7], XmNscaleWidth, 137);
  XtSetArg(args[8], XmNvalue, (int)initialPM);
  XtSetValues(parMassScale, args, 9);
  XtAddCallback(parMassScale, XmNvalueChangedCallback,
                (XtCallbackProc) massParCB, NULL);
  SoXt::show(parMassScale);

  Widget butSep = XtCreateWidget("Separator", xmSeparatorWidgetClass,
				 controls, NULL, 0);
  XtSetArg(args[0], XmNx, 0);
  XtSetArg(args[1], XmNy, 385);
  XtSetArg(args[2], XmNwidth, 137);
  XtSetArg(args[3], XmNheight, 3);
  XtSetValues(butSep, args, 4);
  SoXt::show(butSep);

  XmString startText = XmStringCreate("Scatter", XmFONTLIST_DEFAULT_TAG);
  Widget startButton = XtCreateWidget("PushButton", xmPushButtonWidgetClass,
        			 controls, NULL, 0);

  XtSetArg(args[0], XmNheight, 30);
  XtSetArg(args[1], XmNwidth, 65);
  XtSetArg(args[2], XmNlabelString, startText);
  XtSetArg(args[3], XmNx, 2);
  XtSetArg(args[4], XmNy, 390);
  XtSetValues(startButton, args, 5);
  XtAddCallback(startButton, XmNactivateCallback,
                (XtCallbackProc) scatterCB, NULL);
  SoXt::show(startButton);

  XmString pauseText = XmStringCreate("Pause", XmFONTLIST_DEFAULT_TAG);
  Widget pauseButton = XtCreateWidget("PushButton", xmPushButtonWidgetClass,
        			 controls, NULL, 0);

  XtSetArg(args[0], XmNheight, 30);
  XtSetArg(args[1], XmNwidth, 65);
  XtSetArg(args[2], XmNlabelString, pauseText);
  XtSetArg(args[3], XmNx, 70);
  XtSetArg(args[4], XmNy, 390);
  XtSetValues(pauseButton, args, 5);
  XtAddCallback(pauseButton, XmNactivateCallback,
                (XtCallbackProc) pauseCB, NULL);
  SoXt::show(pauseButton);

  XmString deleteText = XmStringCreate("Delete Unscattered",
				      XmFONTLIST_DEFAULT_TAG);
  Widget deleteButton = XtCreateWidget("PushButton", xmPushButtonWidgetClass,
        			 controls, NULL, 0);

  XtSetArg(args[0], XmNheight, 30);
  XtSetArg(args[1], XmNwidth, 133);
  XtSetArg(args[2], XmNlabelString, deleteText);
  XtSetArg(args[3], XmNx, 2);
  XtSetArg(args[4], XmNy, 422);
  XtSetValues(deleteButton, args, 5);
  XtAddCallback(deleteButton, XmNactivateCallback,
                (XtCallbackProc) deleteCB, NULL);
  SoXt::show(deleteButton);

  XmString newText = XmStringCreate("New Particle Set",
				      XmFONTLIST_DEFAULT_TAG);
  Widget newButton = XtCreateWidget("PushButton", xmPushButtonWidgetClass,
        			 controls, NULL, 0);

  XtSetArg(args[0], XmNheight, 30);
  XtSetArg(args[1], XmNwidth, 133);
  XtSetArg(args[2], XmNlabelString, newText);
  XtSetArg(args[3], XmNx, 2);
  XtSetArg(args[4], XmNy, 454);
  XtSetValues(newButton, args, 5);
  XtAddCallback(newButton, XmNactivateCallback,
                (XtCallbackProc) newCB, NULL);
  SoXt::show(newButton);

  XmString clearText = XmStringCreate("Clear", XmFONTLIST_DEFAULT_TAG);
  Widget clearButton = XtCreateWidget("PushButton", xmPushButtonWidgetClass,
        			 controls, NULL, 0);

  XtSetArg(args[0], XmNheight, 30);
  XtSetArg(args[1], XmNwidth, 65);
  XtSetArg(args[2], XmNlabelString, clearText);
  XtSetArg(args[3], XmNx, 2);
  XtSetArg(args[4], XmNy, 486);
  XtSetValues(clearButton, args, 5);
  XtAddCallback(clearButton, XmNactivateCallback,
                (XtCallbackProc) clearCB, NULL);
  SoXt::show(clearButton);

  XmString quitText = XmStringCreate("Quit", XmFONTLIST_DEFAULT_TAG);
  Widget quitButton = XtCreateWidget("PushButton", xmPushButtonWidgetClass,
        			 controls, NULL, 0);

  XtSetArg(args[0], XmNheight, 30);
  XtSetArg(args[1], XmNwidth, 65);
  XtSetArg(args[2], XmNlabelString, quitText);
  XtSetArg(args[3], XmNx, 70);
  XtSetArg(args[4], XmNy, 486);
  XtSetValues(quitButton, args, 5);
  XtAddCallback(quitButton, XmNactivateCallback,
                (XtCallbackProc) quitCB, NULL);
  SoXt::show(quitButton);

  return controls;
}

void radiusDefCB (Widget scale, XtPointer appData,
			     XtPointer widgetData) {

  XmScaleCallbackStruct *data = (XmScaleCallbackStruct *)widgetData;

  scatterptr->deflectorRadius = (float)data->value / 100.0;
  scatterptr->deflector->setRadius((float)data->value / 100.0);
}

void massDefCB (Widget scale, XtPointer appData,
			   XtPointer widgetData) {

  XmScaleCallbackStruct *data = (XmScaleCallbackStruct *)widgetData;

  scatterptr->deflectorMass = (float)data->value;
  scatterptr->deflector->mass = (float)data->value;
}

void radiusParCB (Widget scale, XtPointer appData,
			     XtPointer widgetData) {

  XmScaleCallbackStruct *data = (XmScaleCallbackStruct *)widgetData;

  scatterptr->pset.radius = (float)data->value / 100.0;
  scatterptr->pset.updateSet();
}

void massParCB (Widget scale, XtPointer appData,
			   XtPointer widgetData) {

  XmScaleCallbackStruct *data = (XmScaleCallbackStruct *)widgetData;

  scatterptr->pset.mass = (float)data->value;
  scatterptr->pset.updateSet();
}

void numberCB (Widget scale, XtPointer appData,
			  XtPointer widgetData) {

  XmScaleCallbackStruct *data = (XmScaleCallbackStruct *)widgetData;

  scatterptr->pset.particleNum = data->value;
  scatterptr->pset.updateSet();
}

void scatterCB (Widget button, XtPointer appData,
			   XtPointer widgetData) {
  sensorptr->schedule();
}

void pauseCB (Widget button, XtPointer appData,
			 XtPointer widgetData) {
  sensorptr->unschedule();
}

void deleteCB (Widget button, XtPointer appData,
			  XtPointer widgetData) {
  sensorptr->unschedule();
  scatterptr->deleteUnscattered();
}

void newCB (Widget button, XtPointer appData,
		       XtPointer widgetData) {
  scatterptr->newParticleSet();
}

void clearCB (Widget button, XtPointer appData,
			 XtPointer widgetData) {
  scatterptr->clear();
}

void quitCB (Widget button, XtPointer appData,
			XtPointer widgetData) {
  exit(0);
}
