#include "PhysicsList.hh"

#include "globals.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleTypes.hh"
#include "G4ParticleTable.hh"

#include "G4Material.hh"
#include "G4MaterialTable.hh"

#include "G4ProcessManager.hh"
#include "G4ProcessVector.hh"

#include "G4DecayTable.hh"
                                                                                
#include "G4MuonDecayChannelWithSpin.hh"

PhysicsList::PhysicsList()
{}

PhysicsList::~PhysicsList()
{}

void PhysicsList::ConstructParticle()
{
  G4Electron::ElectronDefinition();
  G4Positron::PositronDefinition();
  G4NeutrinoE::NeutrinoEDefinition();
  G4AntiNeutrinoE::AntiNeutrinoEDefinition();
  G4MuonPlus::MuonPlusDefinition();
  G4MuonMinus::MuonMinusDefinition();
  G4NeutrinoMu::NeutrinoMuDefinition();
  G4AntiNeutrinoMu::AntiNeutrinoMuDefinition();

  G4DecayTable* MuonPlusDecayTable = new G4DecayTable();
  MuonPlusDecayTable -> Insert(new G4MuonDecayChannelWithSpin("mu+",1.00));
  G4MuonPlus::MuonPlusDefinition() -> SetDecayTable(MuonPlusDecayTable);
                                                                                
  G4DecayTable* MuonMinusDecayTable = new G4DecayTable();
  MuonMinusDecayTable -> Insert(new G4MuonDecayChannelWithSpin("mu-",1.00));
  G4MuonMinus::MuonMinusDefinition() -> SetDecayTable(MuonMinusDecayTable);

}

void PhysicsList::ConstructProcess()
{
  // Define transportation process

  AddTransportation();

  theDecayProcess = new G4DecayWithSpin();

  G4ProcessManager* pManager;
  theParticleIterator->reset();
  while( (*theParticleIterator)() ){
    G4ParticleDefinition* particle = theParticleIterator->value();
    pManager = particle->GetProcessManager();

    if (theDecayProcess->IsApplicable(*particle)) {
      pManager->AddProcess(theDecayProcess);
      pManager ->SetProcessOrderingToLast(theDecayProcess, idxAtRest);
    }
  }

  theMuPlusIonisation = new G4MuIonisation();
  theMuPlusMultipleScattering = new G4MultipleScattering();
  theMuPlusBremsstrahlung=new G4MuBremsstrahlung();
  theMuPlusPairProduction= new G4MuPairProduction();
                                                                                
  theMuMinusIonisation = new G4MuIonisation();
  theMuMinusMultipleScattering = new G4MultipleScattering;
  theMuMinusBremsstrahlung = new G4MuBremsstrahlung();
  theMuMinusPairProduction = new G4MuPairProduction();
                                                                                
  // Muon Plus Physics
  pManager = G4MuonPlus::MuonPlus()->GetProcessManager();
  pManager->AddProcess(theMuPlusMultipleScattering,-1,  1, 1);
  pManager->AddProcess(theMuPlusIonisation,        -1,  2, 2);
  pManager->AddProcess(theMuPlusBremsstrahlung,    -1,  3, 3);
  pManager->AddProcess(theMuPlusPairProduction,    -1,  4, 4);
                                                                                
  // Muon Minus Physics
  pManager = G4MuonMinus::MuonMinus()->GetProcessManager();
  pManager->AddProcess(theMuMinusMultipleScattering,-1,  1, 1);
  pManager->AddProcess(theMuMinusIonisation,        -1,  2, 2);
  pManager->AddProcess(theMuMinusBremsstrahlung,    -1,  3, 3);
  pManager->AddProcess(theMuMinusPairProduction,    -1,  4, 4);

}

void PhysicsList::SetCuts()
{
  // suppress error messages even in case e/gamma/proton do not exist          
  G4int temp = GetVerboseLevel();   
  SetVerboseLevel(0);
  
  //  " G4VUserPhysicsList::SetCutsWithDefault" method sets 
  //   the default cut value for all particle types 
  SetCutsWithDefault();   

  // Retrieve verbose level
  SetVerboseLevel(temp);  
}
