#include "PamG4RegionConstruction.h"

#include "G4SystemOfUnits.hh"
#include <G4Material.hh>
#include <G4ParticleDefinition.hh>
#include <G4Electron.hh>
#include <G4ProcessManager.hh>
#include <G4ProductionCuts.hh>
#include <G4LogicalVolume.hh>
#include <G4VPhysicalVolume.hh>
#include <G4Region.hh>
#include <G4RegionStore.hh>
#include <G4ProductionCutsTable.hh>
#include <G4EmCalculator.hh>

#include <TGeoManager.h>
#include <TGeoVolume.h>
#include <TObjArray.h>
#include <TG4GeometryServices.h>
#include <TG4Limits.h>
PamG4RegionConstruction::PamG4RegionConstruction(const G4String& name): 
  TG4VUserRegionConstruction(), fname(name)
{
/// Standard constructor
}

PamG4RegionConstruction::PamG4RegionConstruction(
                                     G4int verboselevel,
                                     const G4String& name): 
  TG4VUserRegionConstruction(), fname(name), fverboselevel(verboselevel) 
{
/// Destructor
}


void PamG4RegionConstruction::Construct()
{

  if (fverboselevel > 0) {
    G4cout<< "### RANGE Cuts constructed. " << G4endl;
  }

  G4Region* IRONreg = new G4Region("IRON_reg");
  G4Region* TUNGAreg = new G4Region("TUNGA_reg");
  G4Region* He3reg = new G4Region("He3_reg");  
  G4Region* ALUMINIUMreg = new G4Region("ALUMINIUM_reg");
  G4Region* N2GASreg = new G4Region("N2GAS_reg");
  G4Region* SCINTreg = new G4Region("SCINT_reg");
  G4Region* SBARreg = new G4Region("SBAR_reg");
  G4Region* PLASTreg = new G4Region("PLAST_reg");
  G4Region* CADMIUMreg = new G4Region("CADMIUM_reg");
  G4Region* SICALOreg = new G4Region("SICALO_reg");
  G4Region* SITRreg = new G4Region("SITR_reg");
  G4Region* CERAMICreg = new G4Region("CERAMIC_reg");
  G4Region* G10Creg = new G4Region("G10C_reg");
  G4Region* POLYSTYRENEreg = new G4Region("POLYSTYRENE_reg");
  G4Region* MYLARreg = new G4Region("MYLAR_reg");
  G4Region* TIALVAreg = new G4Region("TIALVA_reg");
  G4Region* POLYETHYLENEreg = new G4Region("POLYETHYLENE_reg");
  G4Region* AMG6Mreg = new G4Region("AMG6M_reg");
  G4Region* NYLON6reg = new G4Region("NYLON6_reg");

  
  G4ProductionCuts* IRONcuts = new G4ProductionCuts();
  G4ProductionCuts* TUNGAcuts = new G4ProductionCuts();
  G4ProductionCuts* He3cuts = new G4ProductionCuts();
  G4ProductionCuts* ALUMINIUMcuts = new G4ProductionCuts();
  G4ProductionCuts* N2GAScuts = new G4ProductionCuts();
  G4ProductionCuts* SCINTcuts = new G4ProductionCuts();
  G4ProductionCuts* SBARcuts = new G4ProductionCuts();
  G4ProductionCuts* PLASTcuts = new G4ProductionCuts();
  G4ProductionCuts* CADMIUMcuts = new G4ProductionCuts();
  G4ProductionCuts* SICALOcuts = new G4ProductionCuts();
  G4ProductionCuts* SITRcuts = new G4ProductionCuts();
  G4ProductionCuts* CERAMICcuts = new G4ProductionCuts();
  G4ProductionCuts* G10Ccuts = new G4ProductionCuts();
  G4ProductionCuts* POLYSTYRENEcuts = new G4ProductionCuts();
  G4ProductionCuts* MYLARcuts = new G4ProductionCuts();
  G4ProductionCuts* TIALVAcuts = new G4ProductionCuts();
  G4ProductionCuts* POLYETHYLENEcuts = new G4ProductionCuts();
  G4ProductionCuts* AMG6Mcuts = new G4ProductionCuts();
  G4ProductionCuts* NYLON6cuts = new G4ProductionCuts();

  TObjArray * VolArr = gGeoManager->GetListOfVolumes();
  TIterator *n= (TIterator *)VolArr->MakeIterator();
  TGeoVolume *vol = 0;
  G4LogicalVolume *tmpLV;
   
    
  TString volname="";
  TString matname="";

  while((vol=(TGeoVolume*)n->Next())){
    volname = vol->GetName();
    matname = vol->GetMaterial()->GetName();    
    tmpLV = 0;     
    tmpLV = TG4GeometryServices::Instance()->FindLogicalVolume((G4String)volname);
    LoopDaughters(tmpLV);
  }


  //++++100 keV+++//
  IRONcuts->SetProductionCut(28*mm,"gamma"); // 127.8mm = 994.863 keV  128mm =  1.03095eV    
  IRONcuts->SetProductionCut(25.5*um,"e-");  // 0.737mm=988.422keV 0.739mm=1.00067MeV
  IRONcuts->SetProductionCut(26.*um,"e+");  // 0.787mm=988.422keV  0.788mm=1.00067MeV
  IRONreg->SetProductionCuts(IRONcuts);
  //++++100 keV+++//

  TUNGAcuts->SetProductionCut(16.1*um,"gamma"); // 16.11=10.0745 16.10=9.99505
  TUNGAcuts->SetProductionCut(815.075*nm,"e-");  // 815.075=9.99908 815.0752=10.096
  TUNGAcuts->SetProductionCut(819.1*nm,"e+");  //   819.100=9.92394 819.105=10.0197
  TUNGAreg->SetProductionCuts(TUNGAcuts);

  He3cuts->SetProductionCut(278*m,"gamma"); // 278m=99.0295 keV 279m=109.225keV
  He3cuts->SetProductionCut(79.2*mm,"e-");  // 79.2mm=99.5054mm 79.3mm=100.12keV
  He3cuts->SetProductionCut(81*mm,"e+");  //   81mm=99.5054 81.5mm=100.12
  He3reg->SetProductionCuts(He3cuts);

  //++++100 keV+++//
  ALUMINIUMcuts->SetProductionCut(12.3922*cm,"gamma"); 
  ALUMINIUMcuts->SetProductionCut(64*um,"e-");  
  ALUMINIUMcuts->SetProductionCut(65.6*um,"e+");  
  ALUMINIUMreg->SetProductionCuts(ALUMINIUMcuts);
  //++++100 keV+++//

  //++++100 keV+++//
  N2GAScuts->SetProductionCut(277*m,"gamma"); // 278m=99.0295 keV 279m=109.225keV
  N2GAScuts->SetProductionCut(12.3*cm,"e-");  // 79.2mm=99.5054mm 79.3mm=100.12keV
  N2GAScuts->SetProductionCut(12.6*cm,"e+");  //   81mm=99.5054 81.5mm=100.12
  N2GASreg->SetProductionCuts(N2GAScuts);
  //++++100 keV+++//
  
  //++++100 keV+++//
  SCINTcuts->SetProductionCut(33.8*cm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  SCINTcuts->SetProductionCut(133.*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  SCINTcuts->SetProductionCut(136.*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  SCINTreg->SetProductionCuts(SCINTcuts);
  //++++100 keV+++//
  
  //++++100 keV+++//
  PLASTcuts->SetProductionCut(34.2*cm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  PLASTcuts->SetProductionCut(145.*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  PLASTcuts->SetProductionCut(149.*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  PLASTreg->SetProductionCuts(PLASTcuts);
  //++++100 keV+++//

  //++++100 keV+++//
  CADMIUMcuts->SetProductionCut(6.79*mm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  CADMIUMcuts->SetProductionCut(27.5*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  CADMIUMcuts->SetProductionCut(28.5*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  CADMIUMreg->SetProductionCuts(CADMIUMcuts);
  //++++100 keV+++//

//   SICALOcuts->SetProductionCut(2.172*mm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
//   SICALOcuts->SetProductionCut(4.257*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
//   SICALOcuts->SetProductionCut(4.331*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
//   SICALOreg->SetProductionCuts(SICALOcuts);

  SICALOcuts->SetProductionCut(0.02*mm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  SICALOcuts->SetProductionCut(0.02*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  SICALOcuts->SetProductionCut(0.02*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  SICALOreg->SetProductionCuts(SICALOcuts);

  //++++100 keV+++//
  SITRcuts->SetProductionCut(13.6*cm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  //++++100 keV+++//
  SITRcuts->SetProductionCut(4.257*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  SITRcuts->SetProductionCut(4.331*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  SITRreg->SetProductionCuts(SITRcuts);
 
  SBARcuts->SetProductionCut(2.33*cm,"gamma"); // 278m=99.0295 keV 42mm=10.0695
  SBARcuts->SetProductionCut(5.7447*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  SBARcuts->SetProductionCut(5.8314*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12
  SBARreg->SetProductionCuts(SBARcuts);


  CERAMICcuts->SetProductionCut(3.436*mm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  CERAMICcuts->SetProductionCut(3.6067*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  CERAMICcuts->SetProductionCut(3.6654*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  CERAMICreg->SetProductionCuts(CERAMICcuts);

  G10Ccuts->SetProductionCut(4.63*mm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  G10Ccuts->SetProductionCut(5.45129*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  G10Ccuts->SetProductionCut(5.5422*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  G10Creg->SetProductionCuts(G10Ccuts);

  //++++100 keV+++/
  POLYSTYRENEcuts->SetProductionCut(1.239*m,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  POLYSTYRENEcuts->SetProductionCut(238.07*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  POLYSTYRENEcuts->SetProductionCut(240.04*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  POLYSTYRENEreg->SetProductionCuts(POLYSTYRENEcuts);
  //++++100 keV+++/

  MYLARcuts->SetProductionCut(24.94*cm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  MYLARcuts->SetProductionCut(102.9*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  MYLARcuts->SetProductionCut(105.6*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  MYLARreg->SetProductionCuts(MYLARcuts);

  //++++100 keV+++//
  TIALVAcuts->SetProductionCut(61.4*mm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  TIALVAcuts->SetProductionCut(43.05*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  TIALVAcuts->SetProductionCut(44.5*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  TIALVAreg->SetProductionCuts(TIALVAcuts);
  //++++100 keV+++//

  POLYETHYLENEcuts->SetProductionCut(37.3*cm,"gamma"); // 278m=99.0295 keV 42mm=10.0695 
  POLYETHYLENEcuts->SetProductionCut(135.05*um,"e-");  // .04mm=99.5054mm 79.3mm=100.12keV
  POLYETHYLENEcuts->SetProductionCut(138*um,"e+");  //   4.27 mm=9.18.046 81.5mm=100.12 
  POLYETHYLENEreg->SetProductionCuts(POLYETHYLENEcuts);

  //++++100 keV+++//
  AMG6Mcuts->SetProductionCut(12.8*cm,"gamma"); 
  AMG6Mcuts->SetProductionCut(67*um,"e-"); 
  AMG6Mcuts->SetProductionCut(69*um,"e+");  
  AMG6Mreg->SetProductionCuts(AMG6Mcuts);
  
  NYLON6cuts->SetProductionCut(30.378*cm,"gamma"); 
  NYLON6cuts->SetProductionCut(117*um,"e-");  
  NYLON6cuts->SetProductionCut(120*um,"e+");  
  NYLON6reg->SetProductionCuts(NYLON6cuts);
  //++++100 keV+++//


  // TG4GeometryServices::Instance()->PrintLogicalVolumeStore(); //leave for check

}

void PamG4RegionConstruction::LoopDaughters(G4LogicalVolume * vol){
  
  size_t noDaughters = vol->GetNoDaughters();

  if(noDaughters==0) { if(vol->GetName()!="PAME") SetCuts(vol); return; }

    for (register size_t i=0; i<noDaughters; i++)
    {
      G4LogicalVolume* daughterLVol = vol->GetDaughter(i)->GetLogicalVolume();     
      LoopDaughters(daughterLVol);     
    }
    if(vol->GetName()!="PAME") SetCuts(vol);
}

void PamG4RegionConstruction::SetCuts(G4LogicalVolume * vol){

   G4Region* tmpreg =0;
   G4String matname = vol->GetMaterial()->GetName();
   if(matname=="IRON"){ 
     tmpreg = G4RegionStore::GetInstance()->GetRegion("IRON_reg");                    
     tmpreg->AddRootLogicalVolume(vol);         
   }
   if(matname=="TUNGA"){
     tmpreg = G4RegionStore::GetInstance()->GetRegion("TUNGA_reg");
     tmpreg->AddRootLogicalVolume(vol); 
   }
   if(matname=="He3"){ 
     tmpreg = G4RegionStore::GetInstance()->GetRegion("He3_reg");
     tmpreg->AddRootLogicalVolume(vol);  
   }
   if(matname=="ALUMINIUM"){       
     tmpreg = G4RegionStore::GetInstance()->GetRegion("ALUMINIUM_reg");        
     tmpreg->AddRootLogicalVolume(vol); 
   }
   
   if(matname=="SCINT"){      
     tmpreg = G4RegionStore::GetInstance()->GetRegion("SCINT_reg");         
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="SBAR"){
     tmpreg = G4RegionStore::GetInstance()->GetRegion("SBAR_reg");
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="N2GAS"){
     tmpreg = G4RegionStore::GetInstance()->GetRegion("N2GAS_reg");
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="PLAST"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("PLAST_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="CADMIUM"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("CADMIUM_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="SILICON CA"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("SICALO_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="SILICON TR"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("SITR_reg"); 							  
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="CERAMIC"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("CERAMIC_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
   
   if(matname=="G10C"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("G10C_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="POLYSTYRENE"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("POLYSTYRENE_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="MYLAR"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("MYLAR_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
   if(matname=="TIALVA"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("TIALVA_reg");      
     tmpreg->AddRootLogicalVolume(vol);
   }
  if(matname=="POLYETHYLENE"){         
    tmpreg = G4RegionStore::GetInstance()->GetRegion("POLYETHYLENE_reg");      
    tmpreg->AddRootLogicalVolume(vol);
  }
  if(matname=="AMG6M"){         
     tmpreg = G4RegionStore::GetInstance()->GetRegion("AMG6M_reg");      
     tmpreg->AddRootLogicalVolume(vol);
  }
  if(matname=="NYLON6"){         
    tmpreg = G4RegionStore::GetInstance()->GetRegion("NYLON6_reg");      
    tmpreg->AddRootLogicalVolume(vol);
  }
}




