//
#include <sstream>
//
#include <TObject.h>
#include <TChain.h>
#include <TSystem.h>
#include <TSystemFile.h>
#include <TArrayI.h>
#include <TFile.h>
#include <TTree.h>
#include <TDirectory.h>
#include <TSQLServer.h>
#include <TSQLRow.h>
#include <TSQLResult.h>
//
#include <GLTables.h>
#include <RunInfo.h>
ClassImp(ProcInfo);
ClassImp(SoftInfo);
ClassImp(ItoRunInfo);
//
using namespace std;
//

ProcInfo::ProcInfo() {
  Clear();
}

void ProcInfo::Clear(Option_t *t){
  runID = 0;
  date = "";
  commandLine = "";
  outputFilename = "";
  localDir = "";
  uname = "";
  DB = "";
}

SoftInfo::SoftInfo() {
  Clear();
}

void SoftInfo::Clear(Option_t *t){
  TRIG_ver = "";
  TOF_ver = "";
  AC_ver = "";
  TRK_ver = "";
  ORB_ver = "";
  CAL_ver = "";
  ND_ver = "";
  S4_ver = "";  
  DV_ver = "";
}

UInt_t SoftInfo::GetSWinfo(TString Detector){
  TString sver;
  UInt_t version = 0;
  if ( !strcmp(Detector.Data(),"TRIG") ){
    sver = TRIG_ver;
  }; 
  if ( !strcmp(Detector.Data(),"TOF") ){
    sver = TOF_ver;
  }; 
  if ( !strcmp(Detector.Data(),"AC") ){
    sver = AC_ver;
  }; 
  if ( !strcmp(Detector.Data(),"TRK") ){
    sver = TRK_ver;
  }; 
  if ( !strcmp(Detector.Data(),"CALO") ){
    sver = CAL_ver;
  }; 
  if ( !strcmp(Detector.Data(),"S4") ){
    sver = S4_ver;
  }; 
  if ( !strcmp(Detector.Data(),"DV") ){
    sver = DV_ver;
  }; 
  if ( !strcmp(Detector.Data(),"ND") ){
    sver = ND_ver;
  }; 
  if ( !strcmp(Detector.Data(),"ORB") ){
    sver = ORB_ver;
  }; 
  sver.ReplaceAll("v",1," ",1);
  sver.ReplaceAll("r",1," ",1);
  version = (UInt_t)sver.Atoi();
  return(version);
};

/**
 * Fills a struct cSoftInfo with values from a SoftInfo object (to put data into a F77 common).
 */
void SoftInfo::GetLevel2Struct(cSoftInfo *l2) const{
  l2->FillTrigWith(TRIG_ver);
  l2->FillTofWith(TOF_ver);
  l2->FillAcWith(AC_ver);
  l2->FillTrkWith(TRK_ver);
  l2->FillOrbWith(ORB_ver);
  l2->FillCalWith(CAL_ver);
  l2->FillNdWith(ND_ver);
  l2->FillS4With(S4_ver);
}
/***********************/

ItoRunInfo::~ItoRunInfo() {
  this->GL_RUN::Clear();
}

ItoRunInfo::ItoRunInfo() {
  reprocessing = false;
  updating = false;
  isreadonly = true;
  first_file_entry = 0;
  last_file_entry = 0;
  file_entries = 0;
  totnorun = 0;
  this->GL_RUN::Clear();
  version = new SoftInfo();
  norun = 0;
  runlist = new TArrayI(500);
  file = NULL;
  newtree = NULL;//new TTree();
}

ItoRunInfo::ItoRunInfo(TFile *processFl){
  //
  file=(TFile*)processFl;
  dbc=NULL;
  processFolder = "";
  idRun = 0;
  Detector = "NONE";
  //
  reprocessing = false;
  updating = false;
  first_file_entry = 0;
  last_file_entry = 0;
  file_entries = 0;
  version = new SoftInfo();
  //  glrun = new GL_RUN();
  norun = 0;
  totnorun = 0;
  runlist = new TArrayI(500);
  newtree = NULL;
  //
}



TChain *ItoRunInfo::GetRunTree(TList *fl){
  //
  TChain *Tout = new TChain("Run");	
  // loop over files and create chains	
  TIter next(fl);
  TSystemFile *questo = 0;
  while ( (questo = (TSystemFile*) next()) ) {
    TString name =  questo->GetName();
    Tout->Add(name);
  };
  //
  Tout->SetBranchAddress("RunInfo", GetPointerToRI());
  printf("Run          : set branch address RunInfo\n");
  Tout->SetBranchAddress("SoftInfo", GetPointerToSI());
  printf("Software     : set branch address SoftInfo\n");
  //
  return Tout;    		
  //
}

ItoRunInfo::ItoRunInfo(TSQLServer *db, TFile *processFl, TString processFld){
  //
  file=(TFile*)processFl;
  dbc=(TSQLServer*)db;
  processFolder = processFld;
  //
  reprocessing = false;
  updating = false;
  first_file_entry = 0;
  last_file_entry = 0;
  file_entries = 0;
  version = new SoftInfo();
  norun = 0;
  totnorun = 0;
  runlist = new TArrayI(500);
  //
}

void ItoRunInfo::CopyFromTo(GL_RUN *glrun,GL_RUN *newrun,SoftInfo *sinfo, SoftInfo *newver){
  //
  if ( glrun && newrun ){
    //
//    printf("copy \n");
    //
    newrun->ID = glrun->ID                         ;
    newrun->ID_RUN_FRAG = glrun-> ID_RUN_FRAG                ;
    newrun->ID_ROOT_L0 = glrun->ID_ROOT_L0                 ;
    newrun->ID_ROOT_L2 = glrun->ID_ROOT_L2                 ;
    newrun->RUNHEADER_TIME = glrun->RUNHEADER_TIME             ;
    newrun->RUNTRAILER_TIME = glrun->RUNTRAILER_TIME            ;
    newrun->EV_FROM = glrun->EV_FROM                    ; 
    newrun->EV_TO = glrun->EV_TO                      ; 
    newrun->TRK_CALIB_USED = glrun->TRK_CALIB_USED             ;
    newrun->EFF_WRK_SCHEDULE = glrun->EFF_WRK_SCHEDULE           ;
    newrun->PRH_VAR_TRG_MODE_A = glrun->PRH_VAR_TRG_MODE_A         ;
    newrun->PRH_VAR_TRG_MODE_B = glrun->PRH_VAR_TRG_MODE_B         ;
    newrun->ACQ_BUILD_INFO =glrun->ACQ_BUILD_INFO             ;
    newrun->ACQ_VAR_INFO = glrun->ACQ_VAR_INFO               ;
    newrun->RUNHEADER_OBT = glrun->RUNHEADER_OBT              ;
    newrun->RUNTRAILER_OBT = glrun->RUNTRAILER_OBT             ;
    newrun->RUNHEADER_PKT = glrun->RUNHEADER_PKT              ;
    newrun->RUNTRAILER_PKT = glrun->RUNTRAILER_PKT             ;
    newrun->NEVENTS = glrun->NEVENTS                    ;
    newrun->LAST_TIMESYNC = glrun->LAST_TIMESYNC              ;
    newrun->OBT_TIMESYNC = glrun->OBT_TIMESYNC               ;
    newrun->COMPILATIONTIMESTAMP = glrun->COMPILATIONTIMESTAMP       ;
    newrun->FAV_WRK_SCHEDULE = glrun->FAV_WRK_SCHEDULE           ;
    newrun->RM_ACQ_AFTER_CALIB = glrun->RM_ACQ_AFTER_CALIB         ;
    newrun->RM_ACQ_SETTING_MODE = glrun->RM_ACQ_SETTING_MODE        ;
    newrun->PKT_COUNTER = glrun->PKT_COUNTER                ;
    newrun->PKT_READY_COUNTER = glrun->PKT_READY_COUNTER          ;
    newrun->TRK_CALIB_USED = glrun->TRK_CALIB_USED             ;
    newrun->CAL_DSP_MASK  = glrun->CAL_DSP_MASK               ;
    newrun->BOOT_NUMBER  = glrun->BOOT_NUMBER                ;
    newrun->PHYSENDRUN_MASK_S3S2S12  = glrun->PHYSENDRUN_MASK_S3S2S12                 ;
    newrun->PHYSENDRUN_MASK_S11CRC  = glrun->PHYSENDRUN_MASK_S11CRC                 ;
    newrun->VALIDATION  = glrun->VALIDATION                 ;
    //
  };
  //
  if ( newver && sinfo ){
    //
    newver->TRIG_ver = sinfo->TRIG_ver;
    newver->TOF_ver = sinfo->TOF_ver;
    newver->AC_ver = sinfo->AC_ver;
    newver->TRK_ver = sinfo->TRK_ver;
    newver->ORB_ver = sinfo->ORB_ver;
    newver->CAL_ver = sinfo->CAL_ver;
    newver->S4_ver = sinfo->S4_ver;
    newver->DV_ver = sinfo->DV_ver;
    newver->ND_ver = sinfo->ND_ver;
    //
  };
}

Int_t ItoRunInfo::Update(UInt_t run, TString Detector, TString Version){
  //
  isreadonly = false;
  idRun = run;
  //
  Bool_t debug = false;
  //
  //  Bool_t ismydir = false;
  //
  if ( !strcmp(processFolder.Data(),"") ){
    processFolder = "runinfoFolder";
    //    ismydir = true;
  };
  //
  GL_RUN *oldrun = new GL_RUN();
  GL_RUN *newrun = new GL_RUN();
  SoftInfo *oldver = new SoftInfo();
  SoftInfo *newver = new SoftInfo();
  //
  this->GL_RUN::Clear();
  version->Clear();
  //
  norun = 0;
  //
  Bool_t found = false;
  Int_t error = 0;
  //
  TTree *oldtree = 0;
  //
  // Try to get the tree Run in the processed file
  //
  oldtree = (TTree*)file->Get("Run");  
  //
  // Look for detector's versions if we are updating a single detector
  //
  if ( debug ) printf("Detector -%s- \n",Detector.Data());
  if ( !strcmp(Detector.Data(),"NONE") ){
    version->TRIG_ver = Version;
    version->TOF_ver = Version;
    version->AC_ver = Version;
    version->TRK_ver = Version;
    version->ORB_ver = Version;
    version->CAL_ver = Version;    
    version->S4_ver = Version;
    version->DV_ver = Version;
    version->ND_ver = Version;
  } else {
    if ( !strcmp(Detector.Data(),"TRIG") ) version->TRIG_ver = Version;
    if ( !strcmp(Detector.Data(),"TOF") ) version->TOF_ver = Version;
    if ( !strcmp(Detector.Data(),"AC") ) version->AC_ver = Version;
    if ( !strcmp(Detector.Data(),"TRK") ) version->TRK_ver = Version;
    if ( !strcmp(Detector.Data(),"CALO") ) version->CAL_ver = Version;
    if ( !strcmp(Detector.Data(),"S4") ) version->S4_ver = Version;
    if ( !strcmp(Detector.Data(),"DV") ) version->DV_ver = Version;
    if ( !strcmp(Detector.Data(),"ND") ) version->ND_ver = Version;
    if ( !strcmp(Detector.Data(),"ORB") ) version->ORB_ver = Version;
    if ( strcmp(Detector.Data(),"TRIG") && strcmp(Detector.Data(),"TOF") &&  strcmp(Detector.Data(),"AC") && strcmp(Detector.Data(),"TRK") &&  strcmp(Detector.Data(),"CALO") && strcmp(Detector.Data(),"S4") && strcmp(Detector.Data(),"ND") && strcmp(Detector.Data(),"ORB") && strcmp(Detector.Data(),"DV") ) return(-804);
  };
  //
  if ( !oldtree ) {
    //
    if ( strcmp(Detector.Data(),"NONE") ) return(-803);
    updating = false;
    if ( debug ) printf(" RunInfo: creating Run tree in this file\n");
    //
  } else {
    //
    updating = true;
    if ( debug ) printf(" RunInfo: updating versioning information \n");
    //
  };
  //
  file->cd();
  // 
  // Prepare a new tree to upgrade the contents of the old tree 
  //
  newtree = new TTree("Run-new","PAMELA Level2 data from the GL_RUN table");
  newtree->Branch("RunInfo","GL_RUN",&newrun);
  newtree->Branch("SoftInfo","SoftInfo",&newver);
  //  
  //
  if ( !updating ){
    if ( idRun == 0 ){
      if ( debug ) printf("\n RUNINFO - ERROR: reprocessing data but no RunInfo tree in Level2 file. \n");
      return(-805);
    };
    //
    error = Query_GL_RUN(idRun, dbc);
    //
    if ( error ){
      if ( debug ) printf("\n RUNINFO - ERROR: Query_GL_RUN exited with non zero error\n");
      return(error);
    };
    if ( ID == 0 ){
      if ( debug ) printf("\n RUNINFO - ERROR: no run with ID_RUN = %u \n",idRun);
      return(-5);
    };
    //
    //
    CopyFromTo((GL_RUN*)this,newrun,version,newver);
    //
    // fill the tree;
    //
    newtree->Fill();
    //
    totnorun = 1;
    reprocessing = false;
    first_file_entry = 0;
    if ( EV_TO >= EV_FROM ) last_file_entry = (UInt_t)(EV_TO - EV_FROM);
    norun = 1;
    runlist->AddAt((Int_t)ID,0);
    //
    newtree->SetName("Run");
    //
    file->cd();
    //
    delete newver;
    delete newrun;
    delete oldver;
    delete oldrun;
    //
    return(0);
    //
  } else {
    //
    //
    oldtree->SetBranchAddress("RunInfo",&oldrun);
    oldtree->SetBranchAddress("SoftInfo",&oldver);
    //
    totnorun = oldtree->GetEntries();
    //
    if ( totnorun > 500 ){
      if ( debug ) printf("\n RUNINFO - ERROR: can not handle more than 500 runs!\n");
      return(-806);
    };
    //
    found = false;
    //
    for ( UInt_t run = 0; run < totnorun; run++){
      //
      if ( oldtree->GetEntry(run) <= 0 ) throw -36; 
      //
      CopyFromTo(oldrun,newrun,oldver,newver);
      //
      file_entries += (oldrun->EV_TO - oldrun->EV_FROM + 1);
      //
      if ( debug ) printf("totnorun %i idRun %i newrun->ID %i \n",(int)totnorun,(int)idRun,(int)newrun->ID);
      //
      if ( idRun == 0 || idRun == newrun->ID ) {
	//
	if ( debug ) printf(" Updating run number %u newrun->ID %i \n",idRun,(int)newrun->ID);
	//
	found = true;
	//
	runlist->AddAt(newrun->ID,norun);
	norun++;
	//
	if ( !strcmp(Detector.Data(),"NONE") ){
	  //
	  // update infromations querying the DB
	  //
	  error = Query_GL_RUN(newrun->ID, dbc);
	  //
 	  if ( error ){
 	    if ( debug ) printf("\n RUNINFO - ERROR: Query_GL_RUN exited with non zero error\n");
 	    return(error);
 	  };
	  //
	  CopyFromTo((GL_RUN*)this,newrun,NULL,NULL);
	  //
	} else {
	  //
	  if ( !strcmp(Detector.Data(),"TRIG") ){
	    newver->TRIG_ver = version->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->ND_ver = oldver->ND_ver;
	    if ( strcmp(oldver->TRIG_ver.Data(),"") ) reprocessing = true;
	  };
	  if ( !strcmp(Detector.Data(),"TOF") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = version->TOF_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->ND_ver = oldver->ND_ver;
	    if ( strcmp(oldver->TOF_ver.Data(),"") ) reprocessing = true;
	  };
	  if ( !strcmp(Detector.Data(),"AC") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->ND_ver = oldver->ND_ver;
	    newver->AC_ver = version->AC_ver;
	    if ( strcmp(oldver->AC_ver.Data(),"") ) reprocessing = true;
	  };
	  if ( !strcmp(Detector.Data(),"TRK") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->ND_ver = oldver->ND_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->TRK_ver = version->TRK_ver;
	    if ( strcmp(oldver->TRK_ver.Data(),"") ) reprocessing = true;
	  };
	  if ( !strcmp(Detector.Data(),"ORB") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->ND_ver = oldver->ND_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->ORB_ver = version->ORB_ver;
	    if ( strcmp(oldver->ORB_ver.Data(),"") ) reprocessing = true;
	  };
	  if ( !strcmp(Detector.Data(),"CALO") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->ND_ver = oldver->ND_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->CAL_ver = version->CAL_ver;
	    if ( strcmp(oldver->CAL_ver.Data(),"") ) reprocessing = true;
	  };	
	  if ( !strcmp(Detector.Data(),"S4") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->ND_ver = oldver->ND_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->S4_ver = version->S4_ver;
	    if ( strcmp(oldver->S4_ver.Data(),"") ) reprocessing = true;
	  };
	  if ( !strcmp(Detector.Data(),"DV") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->ND_ver = oldver->ND_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->DV_ver = version->DV_ver;
	    if ( strcmp(oldver->DV_ver.Data(),"") ) reprocessing = true;
	  };
	  if ( !strcmp(Detector.Data(),"ND") ){
	    newver->TRIG_ver = oldver->TRIG_ver;
	    newver->TOF_ver = oldver->TOF_ver;
	    newver->DV_ver = oldver->DV_ver;
	    newver->S4_ver = oldver->S4_ver;
	    newver->AC_ver = oldver->AC_ver;
	    newver->ORB_ver = oldver->ORB_ver;
	    newver->TRK_ver = oldver->TRK_ver;
	    newver->CAL_ver = oldver->CAL_ver;
	    newver->ND_ver = version->ND_ver;
	    if ( strcmp(oldver->ND_ver.Data(),"") ) reprocessing = true;
	  };
	};
	//
	if ( oldrun->EV_TO >= oldrun->EV_FROM ) last_file_entry = first_file_entry + (oldrun->EV_TO - oldrun->EV_FROM + 1);
	//
      } else {
	if ( !found ) first_file_entry += (oldrun->EV_TO - oldrun->EV_FROM + 1);
      };
      //
      file->cd();
      if ( debug ) printf("filling: totnorun %i idRun %i newrun->ID %i \n",(int)totnorun,(int)idRun,(int)newrun->ID);
      newtree->Fill();
      //
    };
    //
    file->cd();
    if ( oldtree ) oldtree->Delete("all");
    newtree->SetName("Run");
    //
    delete newver;
    delete newrun;
    delete oldver;
    delete oldrun;
    //
    if ( !found ){
      if ( debug ) printf("\n RUNINFO - ERROR: no run with ID_RUN = %u \n",idRun);
      return(-5);
    };
    //
    this->Write();
    //    newtree->Write();
  };
//  if ( oldtree ) oldtree->Delete(); // crasha qua in queste righe e se non le metti...
//  if ( newver ) delete newver;
//  if ( newrun ) delete newrun;
//  if ( oldver ) delete oldver;
//  if ( oldrun ) delete oldrun;
  return(0);
}

void ItoRunInfo::Write(){
  file->cd();
  newtree->Write("Run",TObject::kOverwrite);
}

Int_t ItoRunInfo::Read(UInt_t idRun){
  //
  isreadonly = true;
  //
  Bool_t debug = false;
  //
  SoftInfo *newver = new SoftInfo();
  GL_RUN *newrun = new GL_RUN();
  //
  // Try to get the tree Run in the processed file
  //
  newtree = (TTree*)file->Get("Run");  
  // 
  if ( !newtree ) {
    //
    printf("\n RUNINFO - ERROR: no RunInfo tree in Level2 file. \n");
    return(-801);
    //
  } else {
    //
    printf(" RunInfo: opening RunInfo tree \n");
    //
    newtree->SetBranchAddress("RunInfo",&newrun);
    newtree->SetBranchAddress("SoftInfo",&newver);
    //
    totnorun = newtree->GetEntries();
    //
    if ( totnorun > 500 ){
      if ( debug ) printf("\n RUNINFO - ERROR: can not handle more than 500 runs!\n");
      return(-806);
    };
    //
    first_file_entry = 0;
    //
    for ( UInt_t run = 0; run < totnorun; run++){
      //
      if ( newtree->GetEntry(run) <= 0 ) throw -36;
      //
      file_entries += (newrun->EV_TO - newrun->EV_FROM + 1);
      //
      if ( debug ) printf("totnorun %i  newrun->ID %i \n",(int)totnorun,(int)newrun->ID);
      //
      CopyFromTo(newrun,(GL_RUN*)this,newver,version);
      if ( idRun == ID || idRun == 0 ){
	runlist->AddAt(newrun->ID,norun);
	norun++;
      };
      if ( newrun->EV_TO >= newrun->EV_FROM ) last_file_entry = first_file_entry + (newrun->EV_TO - newrun->EV_FROM + 1);
    };
  };
  if ( debug ) printf("norun %i \n",(int)norun);
  Int_t error = 0;
  error = GetRunInfo(idRun);
  delete newver;
  delete newrun;
  if ( error ) return(error);
  return(0);
}    

void ItoRunInfo::Close(){
  reprocessing = false;
  updating = false;
  first_file_entry = 0;
  last_file_entry = 0;
  file_entries = 0;
  norun = 0;
  delete runlist;
  //  file = new TFile();  
  file = 0;  
  //  if ( isreadonly ) newtree->Delete();
}

void ItoRunInfo::Clear(Option_t *t){
  if ( newtree ) newtree->Delete();
}

UInt_t ItoRunInfo::GetRunForEntry(UInt_t entry){
  //
  UInt_t startfrom = 0;
  //
  if ( entry >= (UInt_t)first_file_entry && entry <= (UInt_t)last_file_entry ) return(ID);
  //
  if ( entry > (UInt_t)last_file_entry ){
    for ( UInt_t nrun = 0; nrun < norun; nrun++){  
      if ( ID == (UInt_t)runlist->At(nrun) ) {
	startfrom = nrun+1;
	break;
      };
    };
  } else {
    startfrom = 0;
  };
  //
  if ( startfrom >= norun ) startfrom = 0;
  //
 retry:
  //
  for ( UInt_t nrun = startfrom; nrun < norun; nrun++){  
    GetRunInfo((UInt_t)runlist->At(nrun));
    if ( entry >= (UInt_t)first_file_entry && entry <= (UInt_t)last_file_entry ){
      return((UInt_t)runlist->At(nrun));
    };
  };
  if ( startfrom ){
    startfrom = 0;
    goto retry;
  };
  printf(" ERROR! run not found \n");
  return(0);
}

Int_t ItoRunInfo::GetRunInfo(UInt_t run){
  Bool_t found = false;
  SoftInfo *nwver = new SoftInfo();
  GL_RUN *nwrun = new GL_RUN();
  //
  newtree->SetBranchAddress("RunInfo",&nwrun);
  newtree->SetBranchAddress("SoftInfo",&nwver);
  //
  last_file_entry = 0;
  first_file_entry = 0;
  //
  totnorun = newtree->GetEntries();
  //
  for ( UInt_t nrun = 0; nrun < totnorun; nrun++){  
    if ( newtree->GetEntry(nrun) <= 0 ) throw -36;
    //
    if ( nwrun->ID == run || run == 0 ){
      CopyFromTo(nwrun,(GL_RUN*)this,nwver,version);
      found = true;
      if ( nwrun->EV_TO >= nwrun->EV_FROM ) last_file_entry = first_file_entry + (nwrun->EV_TO - nwrun->EV_FROM + 1);
    };
    if ( !found ) first_file_entry += (nwrun->EV_TO - nwrun->EV_FROM + 1);
  };
  delete nwver;
  delete nwrun;
  if ( found ) return(0);
  return(-800);
}

