#ifndef PAMVMC_DET_GEOM_H
#define PAMVMC_DET_GEOM_H
#include <iostream>

#include <TMap.h>
#include <TObject.h>
#include <TString.h>
#include <TObjString.h>
#include <TList.h>

#include <Riostream.h>
#include <TVirtualMC.h>
#include <TGeoManager.h>
#include <TGeoMatrix.h>

#include "PamVMCMat.h"

struct pMotherProp : public TObject{

  TGeoVolume *fmother;
  Int_t fcopyNo;
  TGeoMatrix *fmothermatrix;
  

  pMotherProp():fmother(0),fcopyNo(-1),fmothermatrix(0){};
  pMotherProp(TGeoVolume *mother, Int_t copyNo, TGeoMatrix *mothermatrix):
    fmother(mother),fcopyNo(copyNo),fmothermatrix(mothermatrix){};

};


class PamVMCDetGeom  : public TObject {

 protected:

  enum kind {MAT,MED,VOL};
  TString fdname;
  TMap fdrot; //Map of geometry transformations
  TObjArray fmotherprop; // Vector of mother volume to be passed as node of other mother volumes
  TMap fmat; //Map of Material
  TMap fmix; // Mixtures
  TMap fmed; // Mediums
  TMap fvol;  // Volumes
  TGeoVolume *fmother; // Mother volume of the detector in case of any

 public:


   PamVMCDetGeom(const char *dname="NoDetGeom" ): 
     fdname(dname), fmother(0)
  {
    
  };

  
  virtual ~PamVMCDetGeom() { 
    fdrot.DeleteAll();
    fmotherprop.Clear(); 
    fmat.DeleteAll();
    fmix.DeleteAll();
    fmed.DeleteAll();
    //delete fmother;
  }

  
  // virtual void ConstructGeometry()=0; 


  TGeoRotation* GetRot(const char* rot){
    return (TGeoRotation*)fdrot(rot);
  }


  Int_t GetMedID(const char *name){ return GetMed(name)->GetId(); }

  TGeoMaterial* GetMat(const char *name){ return (TGeoMaterial*)CheckDef(name,MAT); }
  
  TGeoMedium* GetMed(const char *name){ return (TGeoMedium*)CheckDef(name,MED); }
  
  TGeoVolume* GetVol(const char *name){ return (TGeoVolume*)CheckDef(name,VOL); }

  TObject* CheckDef(const char *name, kind k){
    switch(k){
    case MAT:
      return gGeoManager->GetMaterial(name);
    case MED:
      return gGeoManager->GetMedium(name);
    case VOL:
      return gGeoManager->GetVolume(name);
    default:
      return 0;
    }
  }


  void AddMotherProp(pMotherProp *mp) {SetMotherProp(mp);}

  void AddMotherProp(TObjArray *mp) {fmotherprop.AddAll(mp); }

  void SetMotherProp(pMotherProp *mp) {
    SetMotherProp(mp->fmother,mp->fcopyNo,mp->fmothermatrix);
  }

  void SetMotherProp(TGeoVolume *mv, Int_t cn, TGeoMatrix* mx){  

    fmotherprop.Add(new pMotherProp(mv,cn,mx) );
    }    

  void SetMotherVol(TGeoVolume *mv) { fmother=mv; }

  TObjArray* GetMotherProp(){ return &fmotherprop;}

  void RegisterNodes() { RegisterNodes(&fmotherprop); }

  void RegisterNodes( TObjArray * to ) {
    // Some exception or error printout 
    // should be added to signal that fmother is empty 
    if(fmother) {
      TIterator *p= (TIterator *)(*to).MakeIterator(); 
      pMotherProp *k; 
      while( k=(pMotherProp *) p->Next()) {
	fmother->AddNode((*k).fmother,(*k).fcopyNo,(*k).fmothermatrix);
      }
    } 
  }

  ClassDef(PamVMCDetGeom,1)
};


#endif //PAMVMC_DET_GEOM_H
