#include "UserRunAction.hh"
#include "UserEventAction.hh"
#include "G4Event.hh"
#include "G4Trajectory.hh"
#include "G4VVisManager.hh"
#include "G4SDManager.hh"
#include "G4UnitsTable.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"

#include <iostream>
#include <fstream>
#include <vector>

// Defining actions performed at the beginning and/or the end of each event

// Constructor
UserEventAction::UserEventAction()
{;}

// Destructor
UserEventAction::~UserEventAction()
{;}



void UserEventAction::BeginOfEventAction(const G4Event* event)
{
    // This method specifies the actions that must be performed at the
    // beginning of each event.
    G4int nEvent = event -> GetEventID();
//    G4cout << "---> UserEventAction: Start of event: " << nEvent << G4endl;
    
    
//    // Get primary event informations
//    G4double en_primary    = 0.*MeV;
//    G4double x_primary     = 0.*cm;
//    G4double y_primary     = 0.*cm;
//    G4double z_primary     = 0.*cm;
//    G4double theta_primary = 0.*deg;
//    G4double phi_primary   = 0.*deg;
//    G4int nVertex = event -> GetNumberOfPrimaryVertex();
//    // G4cout << " *** DEBUG " << " nVertex " << nVertex << G4endl;
//    for ( G4int j = 0; j < nVertex; j++) {
//        G4int nPart =  event -> GetPrimaryVertex(j)->GetNumberOfParticle();
//        //G4cout << " *** DEBUG " << " nPart " << nVertex << G4endl;
//        for ( G4int i = 0; i < nPart; i++) {
//            G4ThreeVector position = event -> GetPrimaryVertex(j) -> GetPosition();
//            G4ThreeVector direction = event -> GetPrimaryVertex(j) -> GetPrimary(i) -> GetMomentum();
//            G4double P = direction.mag();
//            en_primary = event->GetPrimaryVertex(j)->GetPrimary(i)->GetMass();
//            G4double E0 = event->GetPrimaryVertex(j)->GetPrimary(i)->GetG4code()->GetPDGMass();
//            en_primary = std::sqrt(P*P+E0*E0);
//            en_primary -= E0;
//            direction = direction*(1./direction.mag());
//            direction = -direction;  // reverse the direction
//            phi_primary = direction.phi();
//            if (phi_primary <0) phi_primary = phi_primary + twopi;
//            theta_primary = direction.theta();
//            x_primary=position.x();
//            y_primary=position.y();
//            z_primary=position.z();
//
////            if (x_primary <0 && y_primary < 0 && z_primary <0) {
////            G4cout << " *** DEBUG " << " position " << position << G4endl;
////            G4cout << " *** DEBUG " << " direction " << direction << G4endl;
////            G4cout << " *** DEBUG " << " P " << P << G4endl;
////            G4cout << " *** DEBUG " << " en_primary " << en_primary << G4endl;
////            G4cout << " *** DEBUG " << " x " << x_primary << G4endl;
////            G4cout << " *** DEBUG " << " y " << y_primary << G4endl;
////            G4cout << " *** DEBUG " << " z " << z_primary << G4endl;
////            G4cout << " *** DEBUG " << " Theta " << theta_primary/deg << G4endl;
////            G4cout << " *** DEBUG " << " Phi " << phi_primary/deg << G4endl;
////            }
//
//        }
//    }


    if(!(nEvent % 100000))
    {
        G4cout << "INFORMATION: event " << nEvent << " in progress..." << G4endl;
    }
    
}


void UserEventAction::EndOfEventAction(const G4Event* event) {
    // This method specifies the actions that must be performed at the
    // end of each event.
//    G4int nEvent = event -> GetEventID();
//    G4cout << "---> UserEventAction: End of event: " << nEvent << G4endl;

    // The number of events is retrieved from the G4Event object
    // Remember: the first event has number 0, therefore we add 1
    G4int nmbEvents = (event -> GetEventID()) + 1;
    

    // The average CPU time is printed if a run has at least 10000 events
    if(!(nmbEvents % 10000))
    {
        G4cout << "INFORMATION: " << nmbEvents << " events processed." << G4endl;
    }
    
}
