#ifndef PAMVMC_DETECTOR_SD_H
#define PAMVMC_DETECTOR_SD_H
#include <iostream>
#include <TClonesArray.h>
#include <TObject.h>
#include <TString.h>
#include <TObjString.h>
#include <TMap.h>
#include <TROOT.h>
#include "PamVMCDetectorHit.h"
#include "PamVMCGeoIDMgr.h"
#include "PamRootManager.h"
#include "PamVMCStack.h"
#include <TParticle.h>
#include <TG4G3Units.h>

enum fin{INSIDE,ENTERING,EXITING};

class PamVMCDetectorSD  : public TObject {

 protected:

  TString fcname;
  TString fdname;
  Int_t fnohit;
  //  PamVMCDetectorHit *fhit; 
  TClonesArray *fHitColl;
  TMap fdmap;
  PamVMCGeoID *fdetID;
  PamVMCDetectorHit fhit;

 public:


  //PamVMCDetectorSD(){}; 
    //  fcname(""), fdname(""), fnohit(0),  fdetID(0), fHitColl(0) { ;};

   PamVMCDetectorSD(
  		   const char *cname="pHitData", 
  		   char *dname="", 
  		   Int_t is=0): 
    fcname(cname), fdname(dname), fnohit(0), fdetID(0)
  {
    if(is) {
     fHitColl=new TClonesArray(fcname.Data(),is); 
    } else {
      fHitColl=new TClonesArray(fcname.Data());
   }
        //    fHitColl->Print();
         ///  cout<<"!!! Created array:" <<fdname.Data()<<" is="<<is<<endl;
     AddGeoID(dname);
           //    fdetID=PamVMCGeoIDMgr::Instance()->GetGeoID(fdname.Data());
  }

  
  virtual ~PamVMCDetectorSD() { delete fHitColl; delete fdetID;}
  
  void PamVMCDetectorSD::Register(){
    
    PamRootManager::Instance()->
      Register(fdname.Data(),"TClonesArray", &fHitColl);
    //    fdname.Print();

     TString a=fHitColl?"exist":"not exist"; 
     cout<<"!!! Registered TREE:" <<fdname.Data()<< endl;
     cout << "HitColl=" <<a.Data() << endl; 
  }

  void AddGeoID(const char * dname){
    TString temp=dname;
    fdetID=new PamVMCGeoID(dname);
    fdmap.Add(new TObjString(temp), fdetID);
    cout <<" Inside AddGeoID "<<fdname.Data() << endl;
    fdmap.Print();
  }

  virtual void CleanHit(){ fhit.CleanHit();}

  virtual void InitHit() {     
    if(fdetID) {
      //      fdetID->FillVolID(); 
      //      fdetID->Print();
      fhit.SetPOS( fdetID->GetID( )) ;
    } else { fhit.SetPOS(-1); }
  }

  virtual void UpdateHit(TVirtualMC *g){ fhit.FillHit(g); }

  // virtual void AddGlobalTime(TVirtualMC *g){
  //    Double_t GlobTime=g->GetStack()->GetCurrentTrack()->T();
  //    fhit.SetTOF(fhit.GetTOF()+GlobTime/TG4G3Units::Time()); 
  //  }

  virtual void SaveHit(){
      pHitData * t=CreateHit();
      *t=*fhit.GetHit();
  }

  virtual void SaveHit(Int_t f){
    pHitData * t=CreateHit(f);
    *t+=*(fhit.GetHit());
  }

  virtual void SaveHit(const char * dname){
    pHitData * t=CreateHit(dname);
    *t=*fhit.GetHit();
  }

  virtual pHitData * CreateHit() 
  { 
    pHitData *hit=  (pHitData *) fHitColl->New(fnohit++);
//     fdetID->FillVolID();
//     hit->fPOS= fdetID->GetID( ) ;
     InitHit();
    return hit;
  }
  virtual void FillVolID(){
    fdetID->FillVolID();
    fhit.SetPOS( fdetID->GetID( )) ;
  }
  virtual pHitData * CreateHit(const char * dname) 
  { 
    fdetID=(PamVMCGeoID*)fdmap(dname); 
    return CreateHit();
  }
  
  virtual pHitData * CreateHit(Int_t flag) {
    if(!fHitColl->At(flag)) { return PamVMCDetectorSD::CreateHit(); } 
    return (pHitData*)fHitColl->At(flag);
  }

   virtual void ClearHitColl(){
     fnohit=0;
     (*fHitColl).Clear();
      }

  virtual void FillHit(fin f,TVirtualMC *g){ 
    switch(f) {
    case ENTERING:
      CleanHit();
       FillVolID();
      InitHit();
     
      //UpdateHit(g);
      //  break;      
    default:
      UpdateHit(g);
      break;      
    }

    switch(f){
    case EXITING:
    // Save hit if energy release is greater than zero
      UpdateHit(g); 
      
      if(fhit.GetEREL()){
	// AddGlobalTime(g);
	SaveHit(fdname.Data());
      }
      break;
    default:
      break;
    }
  }
  

  virtual void Print(const Option_t* ="") const {

    // Print more information like the name
    std::cout<<"DETECTOR "<<fdname<<" HIT COLLECTION"<<std::endl;
    fHitColl->Print();
  }

  ClassDef(PamVMCDetectorSD,1)
};




#endif //PAMVMC_DETECTOR_SD_H
