
#include "ui.h"
#include "uit.h"
#include <Xm/TextF.h>
#include <Xm/ToggleB.h>
#include <Xm/MessageB.h>
#include <Xm/List.h>
#include <Xm/Xm.h>
#include "dest.h"
#include "destP.h"

#include "error.h"
#include "canvas.h"
#include "Common.h"
#include "SamplingProcess.h"


static struct 
{
  Widget       cp;                                   // The control panel.
  Widget       list;                                 // The sampling step list.
  int          selectedPos;                          // The current selected item in this list.
  Widget       addPB,modifyPB,deletePB,upPB,downPB;  // The sampling step list commands push buttons.
  Widget       modulationRadioBox;                   // The modulation radio box.
  Widget       uem,ctem,aem,dpem,ewem;               // Emission toggle buttons.
  Widget       usm,ctsm,brdfsm,arsm,dpsm,ewsm;       // Reflection toggle buutons.
  Widget       nht,vht,pht,fht;                      // Hemicube type radio buttons.
  Widget       na,ne,np;                             // Applic, energy and particles textfields.
  SamplingStep c;
} emd;

static Boolean valid;



static int CheckUserInput()
{
  if ((emd.c.partEnergy<0.0)||(emd.c.partParticles<0.0)||(emd.c.nApp<1))
    return 0;

  if ((emd.c.emissionFlags==0)||(emd.c.sampleFlags==0))
    return 0;

  return 1;
}

static void AddStringToList(char *oldstr,int p)
{
  XmString str;

  str = XmStringCreateLocalized(oldstr);
  XmListAddItemUnselected(emd.list,str,p);
  XmStringFree(str);
  delete oldstr;
}


static void SetStateEmission()
{
  XtVaSetValues(emd.uem,XmNset,ISSET(emd.c.emissionFlags,DE_UNIFORM_EMISSION) ? True : False, NULL);
  XtVaSetValues(emd.ctem,XmNset,ISSET(emd.c.emissionFlags,DE_COSTHETA_EMISSION) ? True : False, NULL);
  XtVaSetValues(emd.aem,XmNset,ISSET(emd.c.emissionFlags,DE_AREA_EMISSION) ? True : False, NULL);
  XtVaSetValues(emd.dpem,XmNset,ISSET(emd.c.emissionFlags,DE_DIRECT_POTENTIAL_EMISSION) ? True : False, NULL);
  XtVaSetValues(emd.ewem,XmNset,ISSET(emd.c.emissionFlags,DE_EQUI_WIN_EMISSION) ? True : False, NULL);

}

static void SetStateReflection()
{
  XtVaSetValues(emd.usm,XmNset,ISSET(emd.c.sampleFlags,DE_UNIFORM_SAMPLE) ? True : False, NULL);
  XtVaSetValues(emd.ctsm,XmNset,ISSET(emd.c.sampleFlags,DE_COSTHETA_SAMPLE) ? True : False, NULL);
  XtVaSetValues(emd.brdfsm,XmNset,ISSET(emd.c.sampleFlags,DE_BRDF_SAMPLE) ? True : False, NULL);
  XtVaSetValues(emd.arsm,XmNset,ISSET(emd.c.sampleFlags,DE_AREA_SAMPLE) ? True : False, NULL);
  XtVaSetValues(emd.dpsm,XmNset,ISSET(emd.c.sampleFlags,DE_DIRECT_POTENTIAL_SAMPLE) ? True : False, NULL);
  XtVaSetValues(emd.ewsm,XmNset,ISSET(emd.c.sampleFlags,DE_EQUI_WIN_SAMPLE) ? True : False, NULL);
}


static void SetStateNums()
{
  char buf[80];
  
  sprintf(buf,"%i",emd.c.nApp);
  XmTextFieldSetString(emd.na, buf);

  sprintf(buf,"%f",emd.c.partEnergy);
  XmTextFieldSetString(emd.ne, buf);

  sprintf(buf,"%f",emd.c.partParticles);
  XmTextFieldSetString(emd.np, buf);
}


static void SetStateModulation()
{
  XtSetSensitive(emd.modulationRadioBox,IS_PATCH_EMISSION(emd.c.emissionFlags));
  XtVaSetValues(emd.nht, XmNset, (emd.c.hemiType==HEMICUBE_NONE) ? True : False, NULL);
  XtVaSetValues(emd.vht, XmNset, (emd.c.hemiType==HEMICUBE_VISIBILITY) ? True : False, NULL);
  XtVaSetValues(emd.pht, XmNset, (emd.c.hemiType==HEMICUBE_PIXEL_COUNT) ? True : False, NULL);
  XtVaSetValues(emd.fht, XmNset, (emd.c.hemiType==HEMICUBE_FORM_FACTOR) ? True : False, NULL);
}


static void SetStateListPushButtons()
{
  int cnt;
  int b = (emd.selectedPos != 0);

  XtVaGetValues(emd.list,
		XmNitemCount, &cnt,
		NULL);

  XtSetSensitive(emd.deletePB,b);
  XtSetSensitive(emd.modifyPB,b);

  XtSetSensitive(emd.upPB,b && (emd.selectedPos > 1) );
  XtSetSensitive(emd.downPB,b && (emd.selectedPos < cnt) );
}


static void addListCallback(Widget,XtPointer,XtPointer)
{
  SamplingStep *ss;

  // Check validity of user inputs
  if (!CheckUserInput())
    return;

  // Build a new step
  ss = new SamplingStep(emd.c.nApp,emd.c.emissionFlags,emd.c.hemiType,emd.c.sampleFlags,emd.c.partEnergy,emd.c.partParticles);

  // insert into the sampling process
  deState.expertSP.insert(ss,deState.expertSP.getSize());

  // update visual
  AddStringToList(emd.c.getDescription(),0);
}


static void deleteListCallback(Widget,XtPointer,XtPointer)
{
  int ic;

  XtVaGetValues(emd.list,XmNitemCount,&ic,NULL);
  if ((emd.selectedPos>0)&&(emd.selectedPos<=ic))
    {
      // Delete into the sampling process
      delete deState.expertSP.remove(emd.selectedPos-1);

      XmListDeletePos(emd.list,emd.selectedPos);
      emd.selectedPos = 0;
      SetStateListPushButtons();
    }
}


static void modifyListCallback(Widget,XtPointer,XtPointer)
{
  SamplingStep *ss;
  int          ic;

  // Check validity of user inputs
  if (!CheckUserInput())
    return;

  XtVaGetValues(emd.list,XmNitemCount,&ic,NULL);
  if ((emd.selectedPos>0)&&(emd.selectedPos<=ic))
    {
      // Delete into the sampling process
      delete deState.expertSP.remove(emd.selectedPos-1);

      XmListDeletePos(emd.list,emd.selectedPos);

      // Build a new step
      ss = new SamplingStep(emd.c.nApp,emd.c.emissionFlags,emd.c.hemiType,emd.c.sampleFlags,emd.c.partEnergy,emd.c.partParticles);
      
      // insert into the sampling process
      deState.expertSP.insert(ss,emd.selectedPos-1);

      // update visual
      AddStringToList(emd.c.getDescription(),emd.selectedPos);

      SetStateListPushButtons();
    }
}

static void upListCallback(Widget,XtPointer,XtPointer)
{
  int          ic;

  XtVaGetValues(emd.list,XmNitemCount,&ic,NULL);
  if ((emd.selectedPos>1)&&(emd.selectedPos<=ic))
    {
      // up into the sampling process
      deState.expertSP.up(emd.selectedPos-1);

      // update visual
      XmListDeletePos(emd.list,emd.selectedPos);
      
      AddStringToList(deState.expertSP.get(emd.selectedPos-2)->getDescription(),emd.selectedPos-1);

      emd.selectedPos = 0;
      SetStateListPushButtons();
    }
}

static void downListCallback(Widget,XtPointer,XtPointer)
{
  int          ic;

  XtVaGetValues(emd.list,XmNitemCount,&ic,NULL);
  if ((emd.selectedPos>0)&&(emd.selectedPos<ic))
    {
      // down into the sampling process
      deState.expertSP.down(emd.selectedPos-1);

      // update visual
      XmListDeletePos(emd.list,emd.selectedPos);

      AddStringToList(deState.expertSP.get(emd.selectedPos)->getDescription(),emd.selectedPos+1);

      emd.selectedPos = 0;
      SetStateListPushButtons();
    }
}


static void ListSelectionCallback(Widget,XtPointer,XtPointer callData)
{
  SamplingStep         *ss;
  XmListCallbackStruct *lcs;
  int          ic;


  lcs = (XmListCallbackStruct *)callData;
  emd.selectedPos = lcs->item_position;

  XtVaGetValues(emd.list,XmNitemCount,&ic,NULL);
  if ((emd.selectedPos>0)&&(emd.selectedPos<=ic))
    {
      ss = deState.expertSP.get(emd.selectedPos-1);
      emd.c.nApp = ss->nApp;
      emd.c.hemiType = ss->hemiType;
      emd.c.partEnergy = ss->partEnergy;
      emd.c.partParticles = ss->partParticles;
      emd.c.emissionFlags = ss->emissionFlags;
      emd.c.sampleFlags = ss->sampleFlags;

      SetStateEmission();
      SetStateReflection();
      SetStateModulation();
      SetStateNums();
    }

  SetStateListPushButtons();
}


static void EmissionModeCallback(Widget,XtPointer clientData,XtPointer)
{
  emd.c.emissionFlags = SWITCHBIT(emd.c.emissionFlags,(int)clientData);
  SetStateModulation();
}


static void ReflectionModeCallback(Widget,XtPointer clientData,XtPointer)
{
  emd.c.sampleFlags = SWITCHBIT(emd.c.sampleFlags,(int)clientData);
}


static void ModulationModeCallback(Widget, XtPointer client_data, XtPointer call_data)
{
  int set = ((XmToggleButtonCallbackStruct *)call_data)->set;
  if (set == XmSET) 
    emd.c.hemiType = (HemicubeType)((int)client_data);
}





static void DismissCallback(Widget,XtPointer,XtPointer)
{
  if (deState.expertSP.getSize()>0)
    XtUnmanageChild(emd.cp);
}



void CreateExpertModeControlPanel(void *parent_widget)
{
  Widget  parent = (Widget)parent_widget;
  Widget  deForm , deTopForm, deForm1, deForm2, deForm3,subform;
  Widget  temp,togglebox;
  int     i,n;
  
  // Create the control panel
  emd.selectedPos = 0;
  emd.cp = CreateDialog(parent, "deExpertControlPanel");

  deTopForm = CreateRowColumn(emd.cp,"deTopForm");
  

  // LIST AND CONTROL FORM
  deForm = CreateForm(deTopForm, "deForm");
  
  CreateLabel(deForm,"deListTitle");

  deForm2 = CreateRowColumn(deForm,"deListForm2");
  emd.addPB = CreatePushButton(deForm2,"deListAddPB",addListCallback,NULL);
  emd.modifyPB = CreatePushButton(deForm2,"deListModifyPB",modifyListCallback,NULL);
  emd.deletePB = CreatePushButton(deForm2,"deListDeletePB",deleteListCallback,NULL);
  emd.upPB = CreatePushButton(deForm2,"deListUpPB",upListCallback,NULL);
  emd.downPB = CreatePushButton(deForm2,"deListDownPB",downListCallback,NULL);

  deForm1 = CreateRowColumn(deForm,"deListForm1");
  emd.list = subform = XmCreateScrolledList(deForm1,"deList",(ArgList)NULL,(Cardinal)0);
  XtAddCallback(subform,XmNbrowseSelectionCallback,ListSelectionCallback,(XtPointer)NULL);
  XtManageChild(subform);
  
  XtManageChild(deForm1);
  XtManageChild(deForm2);

  XtManageChild(deForm);

  
  // Separator
  CreateSeparator(deTopForm,"deSPSeparator");



  // ELEMENT FORM
  CreateLabel(deTopForm,"dePartPart");
  emd.np = CreateFormEntry(deTopForm,NULL,"dePartPartTextf",FET_DOUBLE, (XtPointer)&(emd.c.partParticles), &valid, 0);
  CreateLabel(deTopForm,"dePartPow");
  emd.ne = CreateFormEntry(deTopForm,NULL,"dePartPowTextf",FET_DOUBLE, (XtPointer)&(emd.c.partEnergy), &valid, 0);
  CreateLabel(deTopForm,"deNumApply");
  emd.na = CreateFormEntry(deTopForm,NULL,"deNumApplyTextf",FET_UNSIGNED, (XtPointer)&(emd.c.nApp), &valid, 0);


  deForm = CreateForm(deTopForm, "deForm");

  deForm1 = CreateRowColumn(deForm,"deEmissionForm");
  CreateLabel(deForm1,"deEmissionModeTitle");
  emd.uem = CreateToggleButton(deForm1,"deUniformEmissionMode",ISSET(emd.c.emissionFlags,DE_UNIFORM_EMISSION),EmissionModeCallback,(XtPointer)DE_UNIFORM_EMISSION);
  emd.ctem = CreateToggleButton(deForm1,"deCosThetaEmissionMode",ISSET(emd.c.emissionFlags,DE_COSTHETA_EMISSION),EmissionModeCallback,(XtPointer)DE_COSTHETA_EMISSION);
  emd.aem = CreateToggleButton(deForm1,"deAreaEmissionMode",ISSET(emd.c.emissionFlags,DE_AREA_EMISSION),EmissionModeCallback,(XtPointer)DE_AREA_EMISSION);
  emd.dpem = CreateToggleButton(deForm1,"deDirectPotentialEmissionMode",ISSET(emd.c.emissionFlags,DE_DIRECT_POTENTIAL_EMISSION),EmissionModeCallback,(XtPointer)DE_DIRECT_POTENTIAL_EMISSION);
  emd.ewem = CreateToggleButton(deForm1,"deEquiWinEmissionMode",ISSET(emd.c.emissionFlags,DE_EQUI_WIN_EMISSION),EmissionModeCallback,(XtPointer)DE_EQUI_WIN_EMISSION);

  

  emd.modulationRadioBox = deForm2 = CreateRowColumn(deForm,"deModulationForm");
  CreateLabel(deForm2,"deHemicubeModeTitle");  
  togglebox = CreateRadioBox(deForm2,"deHemicubeMode");
  emd.nht = CreateToggleButton(togglebox,"deNoneHemicubeMode",(emd.c.hemiType == HEMICUBE_NONE),ModulationModeCallback,(XtPointer)HEMICUBE_NONE);
  emd.vht = CreateToggleButton(togglebox,"deVisibilityHemicubeMode",(emd.c.hemiType == HEMICUBE_VISIBILITY),ModulationModeCallback,(XtPointer)HEMICUBE_VISIBILITY);
  emd.pht = CreateToggleButton(togglebox,"dePixelCountHemicubeMode",(emd.c.hemiType == HEMICUBE_PIXEL_COUNT),ModulationModeCallback,(XtPointer)HEMICUBE_PIXEL_COUNT);
  emd.fht = CreateToggleButton(togglebox,"deFormFactorHemicubeMode",(emd.c.hemiType == HEMICUBE_FORM_FACTOR),ModulationModeCallback,(XtPointer)HEMICUBE_FORM_FACTOR);
  XtManageChild(togglebox);

  

  deForm3 = CreateRowColumn(deForm,"deReflectionForm");
  CreateLabel(deForm3,"deSamplingModeTitle");
  emd.usm = CreateToggleButton(deForm3,"deUniformSamplingMode",ISSET(emd.c.sampleFlags,DE_UNIFORM_SAMPLE),ReflectionModeCallback,(XtPointer)DE_UNIFORM_SAMPLE);
  emd.ctsm = CreateToggleButton(deForm3,"deCosThetaSamplingMode",ISSET(emd.c.sampleFlags,DE_COSTHETA_SAMPLE),ReflectionModeCallback,(XtPointer)DE_COSTHETA_SAMPLE);
  emd.brdfsm = CreateToggleButton(deForm3,"deBRDFSamplingMode",ISSET(emd.c.sampleFlags,DE_BRDF_SAMPLE),ReflectionModeCallback,(XtPointer)DE_BRDF_SAMPLE);
  emd.arsm = CreateToggleButton(deForm3,"deAreaSamplingMode",ISSET(emd.c.sampleFlags,DE_AREA_SAMPLE),ReflectionModeCallback,(XtPointer)DE_AREA_SAMPLE);
  emd.dpsm = CreateToggleButton(deForm3,"deDirectPotentialSamplingMode",ISSET(emd.c.sampleFlags,DE_DIRECT_POTENTIAL_SAMPLE),ReflectionModeCallback,(XtPointer)DE_DIRECT_POTENTIAL_SAMPLE);
  emd.ewsm = CreateToggleButton(deForm3,"deEquiWinSamplingMode",ISSET(emd.c.sampleFlags,DE_EQUI_WIN_SAMPLE),ReflectionModeCallback,(XtPointer)DE_EQUI_WIN_SAMPLE);

  
  XtManageChild(deForm1);
  XtManageChild(deForm2);
  XtManageChild(deForm3);

  XtManageChild(deForm);

  XtManageChild(deTopForm);

  // Fill the list
  n = deState.expertSP.getSize();
  for (i=0;i<n;i++)
    AddStringToList((deState.expertSP.get(i))->getDescription(),i+1);


  // Set State info
  SetStateNums();
  SetStateEmission();
  SetStateModulation();
  SetStateReflection();
  SetStateListPushButtons();

  // Dismiss button callback
  XtAddCallback(emd.cp, XmNokCallback, DismissCallback, (XtPointer)NULL);

  // Unmanage the Cancel button
  temp = XmMessageBoxGetChild(emd.cp, XmDIALOG_CANCEL_BUTTON);
  XtUnmanageChild(temp);
}


void ShowExpertModeControlPanel(void)
{
  if (emd.cp)
    XtManageChild(emd.cp);
}


void HideExpertModeControlPanel(void)
{
  if (emd.cp)
    XtUnmanageChild(emd.cp);
}










