#ifndef  __HLOOP_H__
#define  __HLOOP_H__
#include "TFile.h"
#include "TTree.h"
#include "TChain.h"
#include "TArrayI.h"
#include "TSystem.h"
#include "TString.h"
#include "TObject.h"
#include "htree.h"
#include "heventheader.h"
#include "hrecevent.h"
#include "hpartialevent.h"
#include "hgeantheader.h"
#include "hgeantmedia.h"
#include "hcategory.h"
#include <map>
#include <fstream>
#include <iomanip>
using namespace std;
class HSectorSelector : public TObject {
private:
    map<TString,TArrayI> goodSectors;
    Int_t defaultVal;
public:
    HSectorSelector(Bool_t val=kFALSE) {
        defaultVal=val;
    };
    ~HSectorSelector() { goodSectors.clear();};
    void setDefaultVal(Bool_t val) { defaultVal = val;}
    Bool_t readInput(TString infile="",Bool_t print=kFALSE)
    {
	
        goodSectors.clear();
	if(gSystem->AccessPathName(infile.Data())==1){
	    Error("readInput()","Inputfile %s could not be read!",infile.Data());
            return kFALSE;
	}
	TArrayI sectors(6);
	sectors.Reset(0);
        TString file;
        Char_t line[4000];
        Char_t fname[4000];
	ifstream input;
	input.open(infile.Data());
	while (!input.eof()&&input.good()) {
	    input.getline(line,4000);
            file=line;
	    if(file.BeginsWith('#')) { continue; } 
            Int_t n = sscanf(line,"%s %d %d %d %d %d %d",fname,§ors[0],§ors[1],§ors[2],§ors[3],§ors[4],§ors[5]);
            file=fname;
	    if (input.good() && n == 7) {
		if(print)cout<<file<<":  "<<sectors[0]<<" "<<sectors[1]<<" "<<sectors[2]<<" "<<sectors[3]<<" "<<sectors[4]<<" "<<sectors[5]<<endl;
		goodSectors[file] = sectors;
	    }
	}
	input.close();
        return kTRUE;
    }
    Int_t  getNFiles() {return goodSectors.size();}
    Bool_t getSectors(Int_t* sectors,TString filename)
    {
	map<TString,TArrayI>::iterator iter = goodSectors.find(filename);
	if (iter == goodSectors.end()) {
	    
	    for(Int_t s=0;s<6;s++){
		sectors[s] = defaultVal;
	    }
	    return kFALSE;
	} else {
	    for(Int_t s=0;s<6;s++){
		sectors[s]=iter->second.At(s);
	    }
	}
	return kTRUE;
    }
    void printFile(TString filename) {
	map<TString,TArrayI>::iterator iter = goodSectors.find(filename);
	if (iter == goodSectors.end()) {
	    
	    ::Error("printFile()","File %s not found in map!",filename.Data());
	} else {
	    cout<<setw(30)<<filename
		<<" "<<iter->second.At(0)
		<<" "<<iter->second.At(1)
		<<" "<<iter->second.At(2)
		<<" "<<iter->second.At(3)
		<<" "<<iter->second.At(4)
		<<" "<<iter->second.At(5)
		<<endl;
	}
    }
    void print(){
        Int_t ct=0;
	for(map< TString, TArrayI>::iterator iter = goodSectors.begin(); iter != goodSectors.end(); ++iter ) {
	    ct++;
	    cout<<setw(5)<<ct
		<<" "<<setw(30)<<iter->first
		<<" "<<iter->second.At(0)
		<<" "<<iter->second.At(1)
		<<" "<<iter->second.At(2)
		<<" "<<iter->second.At(3)
		<<" "<<iter->second.At(4)
		<<" "<<iter->second.At(5)
		<<endl;
	}
    }
    ClassDef(HSectorSelector,0) 
};
class HLoop;
R__EXTERN HLoop *gLoop;
class HLoop : public TObject {
private:
    TChain*                        fChain; 
    HEventHeader*                   fHead; 
    HGeantMedia*              fGeantMedia; 
    map <TString,HCategory*>       fEvent; 
    map <TString,HPartialEvent*> fPartial; 
    map <TString,Int_t>           fStatus; 
    map <TString,TString>       fPartialN; 
    map <TString,Short_t>      fNameToCat; 
    Long64_t                  fMaxEntries; 
    Long64_t                fCurrentEntry; 
    TString                  fCurrentName; 
    TFile*                   fFileCurrent; 
    TTree*                          fTree; 
    HRecEvent*                  fRecEvent; 
    HSectorSelector       fSectorSelector; 
    Int_t                     fsectors[6]; 
    Int_t                          fRefID; 
    Bool_t                    fFirstEvent; 
    Bool_t               fHasCreatedHades; 
    Bool_t                     fIsNewFile; 
    Bool_t                     fIsSkipped; 
    Bool_t                    fUseTaskSet; 
    Long64_t               fTreeCacheSize; 
    Long64_t        fTreeCacheDefaultSize; 
    Bool_t                    fIsCacheSet; 
    Bool_t        setStatus(TString catname, Int_t stat );
    Bool_t        addCatName(TString catname,Short_t catNum);
public:
    HLoop(Bool_t createHades=kFALSE);
    ~HLoop();
    void           setCurrentLoop() { gLoop=this;}
    Bool_t         addFile     (TString infile);
    Bool_t         addFiles    (TString expression);
    Bool_t         addFilesList(TString filelist);
    Bool_t         addMultFiles(TString commaSeparatedList);
    Bool_t           readSectorFileList(TString filename,Bool_t defaultVal=kFALSE,Bool_t print=kFALSE)  { fSectorSelector.setDefaultVal(defaultVal); return fSectorSelector.readInput(filename,print); }
    HSectorSelector& getSectorSelector()                                       { return fSectorSelector;}
    void             getSectors(Int_t* sectors)                                { for(Int_t s=0;s<6;s++) sectors[s]=fsectors[s];}
    Bool_t           goodSector(Int_t sector)                                  { return ( (sector < 6 && sector >=0 ) ? (fsectors[sector]==1) : kFALSE );}
    HEventHeader*  getEventHeader()            { return fHead; }
    HGeantMedia*   getGeantMedia ()            { return fGeantMedia; }
    TChain*        getChain      ()            { return fChain; }
    TTree*         getTree       ()            { return fTree; }
    Long64_t       getEntries    ()            { return fMaxEntries; }
    HCategory*     getCategory      (TString catname,Bool_t silent = kFALSE);
    Bool_t         getCategoryStatus(TString catname,Bool_t silent = kFALSE);
    HPartialEvent* getPartialEvent  (TString catname,Bool_t silent = kFALSE);
    HGeantHeader*  getGeantHeader   (Bool_t silent=kFALSE);
    TObject*       getFromInputFile(TString name="");
    Bool_t         isSkippedEvent()            { return fIsSkipped; }
    Bool_t         isNewFile(TString& name);
    Bool_t         setInput(TString readCategories = "");
    void           clearCategories();
    Int_t          nextEvent(Int_t iev);
    void           setRefID(Int_t id)          { fRefID = id;}
    void           setTreeCacheSize(Long64_t cs = 8000000);
    void           printCategories();
    void           printChain();
    void           printBranchStatus();
    ClassDef(HLoop,0) 
};
#endif /* !__HLOOP_H__ */