// Written by Peter Stromberger
// based on work of Mirco Deckenhoff
// modified by Bastian Rössler

#include "PrimaryGeneratorAction.hh"
#include "G4Event.hh"
#include "G4ParticleGun.hh"
#include "G4GeneralParticleSource.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
#include "Randomize.hh"
#include "Analysis.hh"
#include "G4SystemOfUnits.hh"

#include "G4RunManager.hh"

PrimaryGeneratorAction::PrimaryGeneratorAction()
{
  gun = InitializeGPS();
}

void PrimaryGeneratorAction::GeneratePrimaries(G4Event* anEvent)
{ 
    gun->GeneratePrimaryVertex(anEvent);
    
    G4double runID = (G4double) G4RunManager::GetRunManager()->GetCurrentRun()->GetRunID();
    G4double eventID = (G4double) anEvent->GetEventID();
    G4double energy = (G4double) gun->GetParticleEnergy();
    G4double xMom = (G4double) gun->GetParticleMomentumDirection()[0];
    G4double yMom = (G4double) gun->GetParticleMomentumDirection()[1];
    G4double zMom = (G4double) gun->GetParticleMomentumDirection()[2];
    
    Analysis::GetInstance()->FillInitialParticle(runID, eventID, energy, xMom, yMom, zMom);

    // Necessery?
    Analysis::GetInstance()->SetGpsPosition(gun->GetParticlePosition());
    Analysis::GetInstance()->SetGpsDirection(gun->GetParticleMomentumDirection());
}

PrimaryGeneratorAction::~PrimaryGeneratorAction()
{
    delete gun;
}

G4GeneralParticleSource* PrimaryGeneratorAction::GetGun()
{
    return gun;
}

G4GeneralParticleSource* PrimaryGeneratorAction::InitializeGPS()
{
    G4GeneralParticleSource * gps = new G4GeneralParticleSource();
    return gps;
}


void PrimaryGeneratorAction::SetOptPhotonPolar()
{
    G4double angle = G4UniformRand() * 360.0*deg;
    SetOptPhotonPolar(angle);
}


void PrimaryGeneratorAction::SetOptPhotonPolar(G4double angle)
{
    if (gun->GetParticleDefinition()->GetParticleName() != "opticalphoton")
    {
        G4cout << "--> warning from PrimaryGeneratorAction::SetOptPhotonPolar() :"
        "the particleGun is not an opticalphoton" << G4endl;
        return;
    }
     	       
    G4ThreeVector normal (1., 0., 0.);
    G4ThreeVector kphoton = gun->GetParticleMomentumDirection();
    G4ThreeVector product = normal.cross(kphoton);
    G4double modul2 = product*product;
 
    G4ThreeVector e_perpend (0., 0., 1.);
    
    if (modul2 > 0.)
        e_perpend = (1./std::sqrt(modul2))*product;
    
    G4ThreeVector e_paralle = e_perpend.cross(kphoton);
 
    G4ThreeVector polar = std::cos(angle)*e_paralle + std::sin(angle)*e_perpend;
    gun->SetParticlePolarization(polar);
}

