#ifndef PAMVMCSDMGR_H
#define PAMVMCSDMGR_H
#include <iostream>

#include "TString.h"
#include "TObjString.h"
#include "TMap.h"
#include "PamVMCDetectorSD.h"

#define NTRPL 6 //number of TOF planes

class PamVMCSDMgr: public TObject {

 private:

  static PamVMCSDMgr * fsd;
  TMap fsdmap;

  //some trigger sd's for fast use
  PamVMCDetectorSD* ftrig_sd [NTRPL];
  TString ftrig_colls[NTRPL];
  Bool_t fisgoodfortrig; // boolean veriable to indicate that 
                         //all triggered sd's are present

 protected:
  PamVMCSDMgr() {
    TString tmp[NTRPL]={"S11Y","S12X","S21X","S22Y","S31Y","S32X"};
    for(Int_t i = 0; i<NTRPL; i++) ftrig_colls[i]=tmp[i];
  };
  
 public:
  
  static PamVMCSDMgr * Instance();

  ~PamVMCSDMgr() {fsdmap.DeleteAll();};

  PamVMCDetectorSD * GetSD(const char *name){
    return (PamVMCDetectorSD*)fsdmap(name);
  }

  void SetSD(const char *name, PamVMCDetectorSD *detSD){
    fsdmap.Add(new TObjString(name),detSD);
  }

  void Register(){

      TMapIter *n= (TMapIter *)fsdmap.MakeIterator(); 
      TObject *o; while(( o=(TObject *) n->Next())) { 
	((PamVMCDetectorSD *)fsdmap.GetValue(o))->Register();
      }
      delete n;
      //check if all trigger SD's are registered. If some TOF layers
      //are missed, return false
      fisgoodfortrig = kTRUE;
      for(Int_t i = 0; i<NTRPL; i++){
	ftrig_sd[i]=(PamVMCDetectorSD *)fsdmap.GetValue(ftrig_colls[i]);
	if(!ftrig_sd[i]) { 
	  cout<<"Warning, trigger SD: "<<ftrig_colls[i]<<" is missed, there are no triggers"<<endl;
	  fisgoodfortrig = kFALSE;
	}
      }
  }
  void Clear(const Option_t* =""){
    TMapIter *n= (TMapIter *)fsdmap.MakeIterator(); 
    TObject *o; while( (o=(TObject *) n->Next())) { 
    ((PamVMCDetectorSD *)fsdmap.GetValue(o))->ClearHitColl();
    }
    delete n;
  }

  void Compress(const Option_t* =""){
    TMapIter *n= (TMapIter *)fsdmap.MakeIterator(); 
    TObject *o; while( (o=(TObject *) n->Next())) { 
    ((PamVMCDetectorSD *)fsdmap.GetValue(o))->Compress();
    }
    delete n;
  }


  void PreEvent(const Option_t* =""){
    TMapIter *n= (TMapIter *)fsdmap.MakeIterator(); 
    TObject *o; while( (o=(TObject *) n->Next())) { 
    ((PamVMCDetectorSD *)fsdmap.GetValue(o))->PreEvent();
    }
    delete n;
  }

  void Digitize(const Option_t* =""){
    TMapIter *n= (TMapIter *)fsdmap.MakeIterator(); 
    TObject *o; while( (o=(TObject *) n->Next())) { 
    ((PamVMCDetectorSD *)fsdmap.GetValue(o))->Digitize();
    }
    delete n;
  }


  void Print( const Option_t* ="") const { 
    cout << "PamVMCSDMgr, list of SD stored " << endl;
    cout<<"pointers: "<<endl;
    TMapIter *n= (TMapIter *)fsdmap.MakeIterator(); 
    TObject *o; while( (o=(TObject *) n->Next())) { 
      cout<<"->DETECTOR:"<<fsdmap.GetValue(o)<<endl;
      ((PamVMCDetectorSD *)fsdmap.GetValue(o))->Print();
    }
    delete n;
    fsdmap.Print();
  }

  Int_t GetTrigger(){
    if(!fisgoodfortrig) return 0;
    

    Int_t s1or = ftrig_sd[0]->GetNhits() + ftrig_sd[1]->GetNhits();
    Int_t s1an = ftrig_sd[0]->GetNhits() * ftrig_sd[1]->GetNhits();

    Int_t s2or = ftrig_sd[2]->GetNhits() + ftrig_sd[3]->GetNhits();
    Int_t s2an = ftrig_sd[2]->GetNhits() * ftrig_sd[3]->GetNhits();

    Int_t s3or = ftrig_sd[4]->GetNhits() + ftrig_sd[4]->GetNhits();
    Int_t s3an = ftrig_sd[4]->GetNhits() * ftrig_sd[4]->GetNhits();

    //TOF2
    if (s1an*s2an*s3an) return 2;
    //TOF1
    if (s1or*s2or*s3or) return 1;
    //TOF4
    if (s2an*s3an) return 4;

    return 0;
    
  }

};

#endif
