//-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//   FEventViewer.c      version 1.03  (2006-04-04)
//
//   Shows PAMELA events - Emiliano Mocchiutti
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//
//   Standard use:
//
//   bash> EventViewer
//
//   For further informations use:
//
//   EventViewer --help
//
//   or
//
//   EventViewer --version
//  
//-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//   Changelog:
//
//   1.02 - 1.03 (2006-04-04): Make it possible to select events with the calorimeter also when generating level1 from level0.
//
//   1.01 - 1.02 (2006-03-22): Read calorimeter ADC2MIP flight conversion file. Do not install FEventviewer.cxx!
//
//   1.00 - 1.01 (2006-03-09): Flight version, read unique YODA file. Many capabilities disabled at the moment (reads only LEVEL0 data).
//
//   0.00 - 1.00 (2006-03-09): Clone of EventViewer.c v9r01.
//
#include <math.h>
#include <stdio.h>
//
#include <iostream>
#include <iomanip>
#include <fstream>
#if (__GNUC__ == 3) && (__GNUC_MINOR__ == 2)
char* operator+( std::streampos&, char* );
#endif
//
#include <TObjectTable.h>
#include <TGClient.h>
#include <TGButton.h>
#include <TGComboBox.h>
#include <TGLabel.h>
#include <TGTextEntry.h>
#include <TGFrame.h>
#include <TGButtonGroup.h>
#include <TGProgressBar.h>
#include <TGMsgBox.h>
#include <TGComboBox.h>
//
#include <TTree.h>
#include <TClassEdit.h>
#include <TObject.h>
#include <TList.h>
#include <TSystem.h>
#include <TSystemDirectory.h>
#include <TString.h>
#include <TFile.h>
#include <TClass.h>
#include <TCanvas.h>
#include <TH1.h>
#include <TH1F.h>
#include <TH2D.h>
#include <TLatex.h>
#include <TPad.h>
#include <TPaveLabel.h>
#include <TLine.h>
#include <TPolyLine.h>
#include <TChain.h>
#include <TApplication.h>
#include <TVirtualX.h>
#include <TGClient.h>
#include <TGWindow.h>
#include <TEllipse.h>
#include <TArrow.h>
#include <TStyle.h>
//
#include <PamelaRun.h>
#include <physics/trigger/TriggerEvent.h>
extern void stringcopy(TString&, const TString&, Int_t, Int_t);
extern void stringappend(TString&, const TString&);
#include <FEVpathtoc.h>
//
#include <FEVpamevcontrol.h>
#include <FEVdetector.h>
#include <FEventViewer.h>
#include <feventvstruct.h>
//
using namespace std;
//
Bool_t existfile(TString filename){
  ifstream myfile;
  myfile.open(filename.Data());
  if ( !myfile ){
    return(false);
  };
  myfile.close();
  return(true);
}

//
// MAIN ROUTINE
//
void ShowEvent(TString filename="help", TString selfile="", TString outDir = ""){
  Int_t ctrlword = 509;
  Int_t FORCELEV = -1;
  TString startingdir = gSystem->WorkingDirectory();
  //
  TApplication app("app",0,0);
  //
  Bool_t firsttime = true;
  //
  Bool_t popup = false;
  //
  gROOT->GetListOfCanvases()->Delete();
  gDirectory->GetList()->Delete();
  //
  // here windows dimension (based on the computer screen size) and position and dimension of figures
  //
  Int_t  xw, yw;
  UInt_t ww, hw;
  gVirtualX->GetWindowSize(gClient->GetRoot()->GetId(),xw,yw,ww,hw);
  Float_t winx = (float)ww*0.80;
  Float_t winy = (float)hw*0.80; // 95
  Float_t winrap = winx/winy;
  //
  //  book the canvas
  //
  TCanvas *figure = new TCanvas("PAMELA event viewer", "PAMELA event viewer",(int)winx,(int)winy);
  //
  // create the PAMELA detector
  //
  FEVdetector *pamela = new FEVdetector(filename,selfile,ctrlword,*figure);
  //
  // Pop up the GUI
  //
  PAMevcontrol *pamgui = 0;
  //
  pamgui = new PAMevcontrol(gClient->GetRoot(),400,800,pamela->var,pamela->level,*figure);
  popup = true;
  pamela->SetGUIPtr(*pamgui);
  if ( outDir == "" ) outDir = startingdir;    
  //
  TTree *otr0 = 0;
  TTree *otr1 = 0;
  TTree *otr2 = 0;
  TTree *otr3 = 0;
  TTree *otr4 = 0;
  TTree *otr5 = 0;
  TTree *otr6 = 0;
  TTree *otr7 = 0;
  TTree *otr8 = 0;
  //
  pamela->var.fl0 = false;
  Int_t i = 0;
  Int_t isOK = 0;
  //
 restart:
  //
  // set boolean variables
  //
  pamela->var.restart = false;
  pamela->var.waitforever = false;
  pamela->var.jumprog = true;
  pamela->var.jumpen = false;    
  pamela->var.goon = false;
  pamela->var.refresh = false;
  pamela->var.alrforc = false;
  //
  // check if we have an input filename
  //
  if ( filename.Data() == "" || !strcmp(filename.Data(),"help") ){
    pamela->var.waitforever = true;
  };
  //
  // chek if we are forcing level0
  //
  if ( pamela->var.fl0 == true ){
    FORCELEV = 0;
  } else {
    FORCELEV = -1;
  };
  //
  //  Define some variables
  //
  pamela->var.bw = 0;
  pamela->var.xxvc = 0.20;
  pamela->var.yxvc = 0.44;
  pamela->var.xyvc = 0.815;
  pamela->var.yyvc = 0.44;
  pamela->var.sfx = 0.81/winrap;
  pamela->var.sfy = 0.81;
  pamela->var.nds4 = pamela->var.sfx;
  pamela->var.xcat = 0.515;
  pamela->var.ycat = 0.74;
  pamela->var.tracknds4 = 1;
  figure->Range(0.,0.,1.,1.);
  gStyle->SetOptDate(0); 
  gStyle->SetOptStat(0);
  gStyle->SetLabelSize(0);
  gStyle->SetNdivisions(1,"X");
  gStyle->SetNdivisions(1,"Y");	
  //
  if ( i < 0 ){
    i = -i;
  } else {
    i = 0;
  };
  isOK = 0;
  //
  // from here to refresh
  //
 refresh:
  //
  // reset pointers
  //
  TFile *headerFile = 0;
  TChain *otr = 0;
  TTree *L0 = 0;
  //
  //  gROOT->Reset();
  //
  // set selection file variables
  //
  if ( pamela->var.refresh ){
    if ( pamela->var.selex ){
      //      pamela->var.selex = true;                               //<<<<<<<<<<<<<<<<<<<<<<<<<<?????????????????????
      selfile = pamela->var.thefilter.Data();
    };
  };
  //
  //
  //  if ( pamela->var.fl0 == true ) {
  //    FORCELEV = 0;
  //  } else {
  //    if ( pamela->var.refresh ) FORCELEV = -1;           //<<<<<<<<<<<<<<<<<<<<<<<<<<?????????????????????
  //  };
  //
  // check the detectors to be shown
  //
  //  if ( !pamela->var.refresh ) pamela->checkctrlword();
  //pamela->checkctrlword();
  //
  // open a dialog if the program is launched without input filename
  //
  if ( firsttime ){
    firsttime = false;
    if ( filename == "" ) pamgui->DIALOG(0," Insert the filename and press load to start ");
  };
  //
  // WAIT for an input filename
  //
  while( pamela->var.waitforever ) { 
    if ( !gROOT->GetListOfCanvases()->FindObject(figure)  ) { 
      pamgui->Terminate();
    };
    gSystem->ProcessEvents(); 
    gSystem->Sleep(10);
  };
  //
  if ( pamela->var.restart ){
    filename = pamela->var.thefilename.Data();
    goto restart;
  };
  //
  // check if we are forcing level0 data
  //
  if ( FORCELEV != -1 ) {
    printf("\n WARNING: FORCING LEVEL%i DATA \n\n",FORCELEV);
    if ( !pamela->var.alrforc ) {
      pamgui->DIALOG(1," Forcing LEVEL0 data ");
      pamela->var.alrforc = true;
    };
  };
  //
  // LOAD SELECTION FILE
  //    
  if ( selfile == ""  ){
    //if ( !pamela->var.selex ) pamgui->DIALOG(0," Selection file unloaded ");
    if ( pamela->var.selex ) pamgui->DIALOG(0," Selection file unloaded ");
    pamela->var.selex = false;
  } else {
    //
    // determine where to find the headers
    //
    gROOT->Reset();
    stringstream paminc;
    paminc.str("");
    const char *testinc = pathtoinclude();	
    paminc << testinc;
    //
    stringstream carica;
    //
    // load the structure header
    //
    carica.str("");
    carica << paminc.str().c_str() << "/feventvstruct.h";
    gROOT->LoadMacro(carica.str().c_str());
    //    carica.str("");
    //    carica << paminc.str().c_str() << "/CaloNuclei.h";
    //    gROOT->LoadMacro(carica.str().c_str());
    //
    // load the selection macro
    //
    Int_t chkload = gROOT->LoadMacro(selfile);
    //
    pamela->var.selex = false;
    //
    if ( chkload ){
      //
      // not able to open the selection file
      //
      stringstream dialog;
      dialog.str("");
      dialog << pamela->var.thefilter.Data();
      dialog << " : no such file!";
      pamgui->DIALOG(2,dialog.str().c_str());
      printf("\n\n ERROR! cannot read the selection file you give me as input! \n");
      pamela->var.selex = false;
      printf("\n WARNING! no selection file loaded! \n\n");
      pamgui->DIALOG(1," No selection file loaded! ");
      selfile = "";
      //
      // clear field in the GUI
      //
      pamgui->clearselfi();
    } else {
      //
      // ok, selection file loaded
      //
      printf("\n\n Selection file loaded \n\n The first event will be shown anyway. \n\n");			    
      //
      if ( !pamela->var.selex ) pamgui->DIALOG(0," Selection file successfully loaded ");
      //
      pamela->var.selex = true;
    };
  };
  //
  //  LOAD FILES    
  //
  //
//   if ( headerFile ) headerFile->Close();
//   if ( otr ) otr->Delete();
//   if ( L0 ) L0->Delete();

  //
  // check if user has given as input a correct path 
  //
  ifstream myfile;
  myfile.open(filename.Data());
  if ( !myfile ){
    if ( filename != "" ){
      printf("ERROR: no such file, exiting...\n");
      stringstream hfile;
      hfile.str("");
      hfile << filename.Data();
      hfile << " : no such file! ";
      pamgui->DIALOG(2,hfile.str().c_str());
    };
    pamela->var.waitforever = true;
    goto refresh;
  };
  myfile.close();
  //
  // ok, open file and determine if it is a YODA or DARTHVADER file
  //

  headerFile=new TFile(filename.Data());
  if ( FORCELEV == 0 ){
    pamela->level.file = 0;
    L0 = (TTree*)headerFile->Get("Physics");
    if ( !L0 ){
      printf("ERROR: no Physics tree...\n");
      pamgui->DIALOG(2,"No Physics tree in this file");
      pamela->var.waitforever = true;
      goto refresh;
    }
  } else {
    pamela->level.file = 2; 
    otr0 = (TTree*)headerFile->Get("Trigger");
    otr1 = (TTree*)headerFile->Get("Calorimeter");
    otr2 = (TTree*)headerFile->Get("Tracker");
    otr3 = (TTree*)headerFile->Get("NeutronD");
    otr4 = (TTree*)headerFile->Get("OrbitalInfo");
    otr5 = (TTree*)headerFile->Get("S4");
    otr6 = (TTree*)headerFile->Get("ToF");
    otr7 = (TTree*)headerFile->Get("Run");
    otr8 = (TTree*)headerFile->Get("Anticounter");
    if ( !otr0 && !otr1 && !otr2 && !otr3 && !otr4 && !otr5 && !otr6 && !otr7 && !otr8 ){
      L0 = (TTree*)headerFile->Get("Physics");      
      pamela->level.file = -1;
    } else {
      stringstream dddec;
      dddec.str("");
      dddec << " +ALL +RUN +CAL1 -TRKh -TRK1 ";
      if ( !otr0 ){
	dddec << " -TRG "; 
	pamela->var.TRG = 0;
	otr0 = otr1;
      };
      if ( !otr1 ){
	dddec << " -CAL "; 
      	pamela->var.CALO = 0;
	if ( !otr0 ) otr0 = otr2;
      };
      if ( !otr2 ){
	dddec << " -TRK2 -TRK "; 
      	pamela->var.TRK = 0;
	if ( !otr0 ) otr0 = otr3;
      };
      if ( !otr3 ){
	dddec << " -ND "; 
      	pamela->var.ND = 0;
	if ( !otr0 ) otr0 = otr4;
      };
      if ( !otr4 ){
	dddec << " -ORB "; 
	pamela->var.ORB = 0;
	if ( !otr0 ) otr0 = otr5;
      };
      if ( !otr5 ){
	dddec << " -S4 "; 
      	pamela->var.S4 = 0;
	if ( !otr0 ) otr0 = otr6;
      };
      if ( !otr6 ){
	dddec << " -TOF "; 
      	pamela->var.TOF = 0;
	if ( !otr0 ) otr0 = otr8;
      };
      if ( !otr7 ){
	dddec << " -RUN "; 
	pamela->var.RUN = 0;
      };
      if ( !otr8 ){
	dddec << " -AC ";
      	pamela->var.AC = 0;
      };
      pamela->SetDDEC(dddec.str().c_str());
    };
    if ( !otr0 && !otr1 && !otr2 && !otr3 && !otr4 && !otr5 && !otr6 && !otr7 && !otr8 && !L0 ){
      pamela->level.file = -1;
      printf("ERROR: nor Physics nor Run tree...\n");
      pamgui->DIALOG(2,"Nor Physics nor Run tree in this file");
      pamela->var.waitforever = true;
      goto refresh;
    };
  };
  headerFile->Close("R");
  //
  if ( pamela->level.file != 2 ){
    printf(" This is a YODA (level0) file \n");
  } else {
    printf(" This is a DARTHVADER (level2) file \n");
  };
  //
  // Disable on the GUI the buttons that cannot be used with this file
  //
  pamgui->CheckLevel();
  //
  // Load the file
  //
  if ( otr0 || L0 ){
    otr = pamela->Load(filename.Data());
    if ( !otr ){
      pamela->level.file = -1;
      printf("ERROR: problems opening file...\n");
      pamgui->DIALOG(2,"Problems opening file");
      pamela->var.waitforever = true;
      goto refresh;
    };
  } else {
    pamela->level.file = -1;
    printf("ERROR: problems with TTree while opening file...\n");
    pamgui->DIALOG(2,"Problems opening file");
    pamela->var.waitforever = true;
    goto refresh;
  };
  //
  printf("\n");
  //
  // get the number of entries
  //
  if ( !otr ) printf(" AGH! \n");
  //
  Long64_t nevents = otr->GetEntries();
  printf(" The file contains %i physics events \n",(int)nevents);
  //
  // check we have at least one event
  //
  if (nevents<=0) {
    //    headerFile->Close();
    printf("The file is empty, exiting...\n");
    pamgui->DIALOG(0," The file contains no physics data! ");
    pamela->var.waitforever = true;
    goto refresh;
  }
  //
  // Check that given input are inside the boundary conditions 
  //
  pamela->minevent = 0;
  pamela->maxevent = nevents - 1;
  //
  // Determine the boundaries
  //
  pamela->GetWindow();
  Int_t lastevno = pamela->lastevno;
  Int_t firstevno = pamela->firstevno;
  //
  // display the first event (unless we are refreshing only the window)
  //
  if ( !pamela->var.refresh ) i = pamela->minevent;
  pamela->var.refresh = false;
  //
  pamgui->RefreshButtons();
  //
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //  MAIN LOOP STARTS HERE:
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  //
  while ( 1 ){
    //
    // update progress bar
    //
    if ( popup ) pamgui->increment((float)(i+1)*100./(float)nevents);
    //
    // clear canvas and variables
    //
    pamela->ClearVariables();
    //
    // get entry i
    //
    pamela->GetEntry(i);
    //
    // call the filter to select events (if filter file is given)
    //	
    isOK = pamela->SelectEvent();
    //
    // if the event is selected go on
    //
    if ( isOK ) {
      //
      // reset working  variables
      //
      printf("\n\n\n\n\n\n\n\n\n\n");
      pamela->SetEntry(i);
      pamela->si = i;
      pamela->var.doflag = 1;
      pamela->var.i = i;
      pamela->var.nevents = nevents;
      pamela->var.lastevno = lastevno;
      pamela->var.firstevno = firstevno;
      //
      printf("\n");
      //
      // disable "stop" button in the GUI
      //
      pamgui->StopSearching();
      //
      // make the canvas editable and clear it
      //
      figure->SetEditable(kTRUE);
      figure->Clear();
      figure->SetFillColor(10);
      figure->cd();
      //
      // retrieve general info for the event (OBT, pkt_num, etc. etc.)
      //
      pamela->GetGeneralInfo();
      //
      // display the event
      //
      pamela->DisplayEvent();
      //
      // prepare the string for the figure filename
      //
      char *bw;
      if ( pamela->var.bw ){
	bw = "_bw";
      } else {
	bw = "";
      };
      TString filenm = pamela->var.thefilename;
      const string fil = gSystem->BaseName(filenm.Data());
      Int_t posiz = fil.find(".root");
      TString file2;
      if ( posiz == -1 ){
	file2 = gSystem->BaseName(filename.Data());
      } else {
	Int_t posiz2 = 0;
	stringcopy(file2,gSystem->BaseName(filename.Data()),posiz2,posiz);
      };
      const char *figrec = file2;
      const char *outdir = outDir;
      stringstream figsave;     
      figsave.str("");
      figsave << outdir << "/";
      figsave << figrec;
      figsave << "_ev_";
      figsave << (pamela->var.i+1);
      figsave << bw;
      pamela->var.svas=figsave.str().c_str();

      //      printf(" qua %s \n",figsave.str().c_str());
      //
      // upgrade the figure filename in the GUI
      //
      pamgui->upgrnamfi();
      //
      // WAIT for user input
      //
      pamela->var.jumpen = false;
      while( !pamela->var.goon && !pamela->var.refresh && !pamela->var.restart ) { 
	if ( !gROOT->GetListOfCanvases()->FindObject(figure)  ) { 
	  pamgui->Terminate();
	};
	gSystem->ProcessEvents(); 
	gSystem->Sleep(10);
      };
      //
      // interpret user input
      //
      pamela->var.goon = false;
      if ( pamela->var.refresh || pamela->var.restart ){
	if ( pamela->GetL2() ) pamela->GetL2()->Reset();
	if ( pamela->level.file != 2 ) pamela->GetChain()->Delete();
	otr = NULL;
	//	if ( headerFile ) headerFile->Close("R");
	if ( pamela->var.refresh ) goto refresh;
	if ( pamela->var.restart ){
	  filename = pamela->var.thefilename.Data();
	  goto restart;
	};
      };
      //
      i = pamela->var.i;
      if ( i != pamela->si ) pamela->OOBT = 1000000000;
      if ( pamela->maxevent < i ) {
	pamela->maxevent = nevents;
	printf("WARNING: you have chosen an event number out of the starting range.\n         Range extended to %i\n\n",pamela->maxevent);		
      };
      // 
    };
    //
    // if the returned entry is -1 it means we must start again from the first event going forward (doflag=1)
    //
    if ( pamela->GetThisEntry() == -1 ){
      pamela->var.doflag = 1;
      i = pamela->minevent;
    };
    //
    // doflag = 2 means "go backward" (check for lower boundary)
    //
    if ( pamela->var.doflag == 2 && i == 0 ) {
      printf("\n WARNING: Cannot go backward! Going forward. \n");
      pamela->var.doflag = 1;
    };
    if ( pamela->var.doflag == 2 && i>0 ) i--;
    //
    // doflag = 1 means go forward (the check on the upper boundary is made in FEVpamevcontrol)
    // 
    if ( pamela->var.doflag == 1 ) i++;
    //
    // if in selection mode, print out a event progress bar in the text window:
    //
    if ( !pamela->var.selex || i == pamela->minevent ){
      // do nothing
    } else {
      if ( (pamela->maxevent-pamela->minevent) != 0 ){
	if((100*(i-pamela->minevent)/(pamela->maxevent-pamela->minevent))<10.){
	  printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8);
	} else {
	  printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8);
	};   
      };
    };

  };
  //
  // END OF THE MAIN LOOP AND OF THE MAIN PROGRAM
  //
  printf("\n");    
  printf(" ...done! \n\n");
  return;
}
