#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 "PamVMCDigMgr.h"
#include "PamVMCGeoIDMgr.h"
#include "PamRootManager.h"
#include "PamVMCStack.h"
#include <TParticle.h>


enum fin{INSIDE,ENTERING,EXITING};

class PamVMCDetectorSD  : public TObject {


 protected:

  TString fcname;
  TString fdname;
  Int_t fnohit;
  fin ffi;
  TClonesArray *fHitColl;
  TMap fdmap;
  PamVMCGeoID *fdetID;
  PamVMCDetectorHit * fhit;
  PamVMCDigitizer * fdig;

 public:


   PamVMCDetectorSD(
  		   const char *cname="PamVMCDetectorHit", 
  		   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());
   }
    fhit = new PamVMCDetectorHit();

    fdig = (PamVMCDigitizer*)PamVMCDigMgr::Instance()->GetDIG(dname);

    AddGeoID(dname);
  }

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

     TString a=fHitColl?"exist":"not exist";  
   }
   
   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) {
       fhit->SetPOS( fdetID->GetID( )) ;
     } else { fhit->SetPOS(-1); }
   }
   
   virtual void UpdateHit(TVirtualMC *g){ fhit->FillHit(g); }
   
   virtual void SaveHit(){
     PamVMCDetectorHit * k=CreateHit();
     k=fhit;
   }
   
   virtual void SaveHit(Int_t f){
     PamVMCDetectorHit * k=CreateHit(f);
     *k+=*fhit;
   }
   
   virtual void SaveHit(const char * dname){
     PamVMCDetectorHit * k=CreateHit(dname);
     *k=*fhit;
   }
   
   virtual PamVMCDetectorHit * CreateHit() 
     { 
       PamVMCDetectorHit *hit=  (PamVMCDetectorHit *) fHitColl->New(fnohit++);
       InitHit();
       return hit;
     }
   
   virtual void FillVolID(){
    fdetID->FillVolID();
    fhit->SetPOS( fdetID->GetID( )) ;
   }
   
  virtual PamVMCDetectorHit * CreateHit(const char * dname) 
    { 
      fdetID=(PamVMCGeoID*)fdmap(dname); 
      return CreateHit();
    }
  
  virtual PamVMCDetectorHit * CreateHit(Int_t flag) { 
    if(!fHitColl->At(flag)) { 
      PamVMCDetectorHit *hit=  (PamVMCDetectorHit *) fHitColl->New(flag);
      InitHit();
      return hit; 
    } 
    return (PamVMCDetectorHit*)fHitColl->At(flag);
  }
  
  virtual void PreEvent(){/* this method was created 
			     for zeroing digits in common area.
			     calls from application before each event*/};
  
  virtual void Compress(){ (*fHitColl).Compress(); };

  virtual void Digitize(){/*this method do  pre-digitize action,
			    ex. calculate strips energy release
			    (create something to be digitized (if any).
			    calls from application*/ }
  
  
  virtual void ClearHitColl(){
    fnohit=0;
    (*fHitColl).Clear("C");
  }

  virtual void FillHit(fin f,TVirtualMC *g){
    ffi=f;
    switch(f) {
    case ENTERING:
      CleanHit();
      FillVolID();
      InitHit();         
    default: 
      UpdateHit(g);
      break;      
    }
    
    switch(f){
    case EXITING:
      // Save hit if energy release is greater than zero
      if(fhit->GetEREL()){
	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
