#ifndef PAMVMCRNDMGR_H
#define PAMVMCRNDMGR_H
#include <iostream>
#include <TString.h>
#include <TObjArray.h>
#include <TRandom3.h>
#include <TSystem.h>
#include <TMap.h>
#include "PamVMCOptMgr.h"
#include "PamRootManager.h"
//This class holds few different random objects
//one for each digitization procedure,
//include Trk digitizations during stepping

using std::cout;
using std::endl;

#define RNDDEBUG 0

class PamVMCRndMgr: public TObject 
{
 private:

  static PamVMCRndMgr * rm;
  TObjArray *frndArr; // An array of random objects; 
  TMap frndmap; //map which holds all actual random objects
  
  

 protected:
  PamVMCRndMgr() 
    {
      
      frndArr = new TObjArray();
      frndArr->SetOwner(kTRUE);
      if (PamVMCOptMgr::Instance()->GetSaveMode() == ALL_DETECTORS){
	PamRootManager::Instance()->Register("RNDM","TObjArray",&frndArr);
	if (RNDDEBUG){
	  cout<<"Random objects Map was created and branch registered" <<endl;
	}
      }
    }
  PamVMCRndMgr( TString ext_dig )
    {
      frndArr = new TObjArray();
      cout<<"Random objects Map was created and branch registered" <<ext_dig<<endl;
    }

  virtual ~PamVMCRndMgr()
    {
      delete frndArr;
    }

 public:
  
  static PamVMCRndMgr * Instance();
  static PamVMCRndMgr * Instance_ext(); //Another way to call instance... for ext_dig constructor

  /* Used only by PamVMCTrkF77 */
  Double_t GenRandom(const char* name){
    if((TRandom3*)frndmap(name))
      return ((TRandom3*)frndmap(name))->Uniform();
    else
      {
	cout<<"Error while calling RndMgr::GenRandom, object not found"<<endl;
	return 0.;
      }
  }

  void RegisterRandom(const char* name, TRandom3 *detrnd){
    frndmap.Add(new TObjString(name), detrnd);
    if(RNDDEBUG){
      cout<<"RegisterRandom to rnd for "<<name<<endl;
      frndmap.Print();
    }
  }

 
  
  void MakeRandomClones()
  {
    if(RNDDEBUG) cout<<" Snapshot of random objects done"<<endl;
    TMapIter *n= (TMapIter *)frndmap.MakeIterator(); 
    TObject *o; while( (o=(TObject *) n->Next())) { 
      TRandom3 *tmp = (TRandom3*)frndmap.GetValue(o);
      frndArr->Add(tmp->Clone());
      if(RNDDEBUG) {
	cout<<"Obj: "<<tmp<<" det: "<<tmp->GetName()<<endl;
	tmp->Dump();
      }
    }
    delete n;
  }


  void ClearColl() {  (*frndArr).Clear("C"); }
  void Compress() { (*frndArr).Compress(); }
};

#endif
