// Written by Peter Stromberger
// based on work of Mirco Deckenhoff


#ifndef ANALYSIS_HH_
#define ANALYSIS_HH_ 1

#include "G4Event.hh"
#include "G4Run.hh"
#include "G4ThreeVector.hh"
#include "TFile.h"
#include "TH2F.h"
#include "TH1F.h"
#include "TTree.h"
#include "TObject.h"

#include <vector>
#include <iostream>


class Analysis {

public:
  
    static Analysis* GetInstance()
    {
        if ( Analysis::singleton == NULL ) Analysis::singleton = new Analysis();
    
        return Analysis::singleton;
    }

    virtual ~Analysis() {};
    void PrepareNewEvent(const G4Event* anEvent);
    void PrepareNewRun(const G4Run* anRun);
    void EndOfRun();
    void Close();


    // Adds a new row to the tree : detectedPhotons
    void FillDetectedPhotons(Double_t runID, Double_t eventID, Double_t detNumb, Double_t xPixel,
                             Double_t yPixel, Double_t energy,
                             Double_t time, Double_t length, Double_t absTime,
                             Double_t x, Double_t y, Double_t z,
                             Double_t px, Double_t py, Double_t pz,
                             Double_t vertexX, Double_t vertexY, Double_t vertexZ,
                             Double_t vertexPx, Double_t vertexPy, Double_t vertexPz,
                             Int_t trackId,
                             Int_t creatorProcess, Int_t parentId);
	
    // Adds a new to to the tree : trigger
    void FillTrigger(Double_t runID, Double_t eventID, Double_t edep,
                     Double_t xPos, Double_t yPos, Double_t zPos);

    // Adds a new to to the tree : initialParticle
    void FillInitialParticle(Double_t runID, Double_t eventID,
                             Double_t energy, Double_t xMom, Double_t yMom, Double_t zMom);

    // Adds a new to to the tree : primaryParticleTrack
    void FillPrimaryParticleTrack(Double_t runID, Double_t eventID, Double_t xPos, Double_t yPos, Double_t zPos);

    // Adds a new to to the tree : energyTrack
    void FillEnergyTrack(Double_t runID, Double_t eventID, Double_t energy, Double_t trackL);

    void SetGpsPosition(G4ThreeVector position);
    void SetGpsDirection(G4ThreeVector directtion);


  

    char* FileName();


    void IncreaseReflectionsAtMirror(Int_t trackId);
    void IncreaseReflectionsAtFibreSurface(Int_t trackId);
    void IncreaseTotalReflectionsAtCladCladInterface(Int_t trackId);
    void IncreaseTotalReflectionsAtCoreCladInterface(Int_t trackId);
    void IncreaseFresnelReflectionsAtCladCladInterface(Int_t trackId);
    void IncreaseFresnelReflectionsAtCoreCladInterface(Int_t trackId);

    void IncreaseRefractionsAtCladCladInterface(Int_t trackId);
    void IncreaseRefractionsAtCoreCladInterface(Int_t trackId);

    void IncreaseRayleighScatterings(Int_t trackId);

    void IncreaseReflectionRefractionAndScatteringVectors(Int_t trackId);


    void IncreaseLengthInCore(Int_t trackId, Float_t lengthValue);
    void IncreaseLengthInInnerCladding(Int_t trackId, Float_t lengthValue);
    void IncreaseLengthInOuterCladding(Int_t trackId, Float_t lengthValue);

    void IncreaseLengthVectors(Int_t trackId);
  

private:

    Analysis();
    static Analysis* singleton;

    TFile* dataFile;
    char fileName[40];

    TTree* detectedPhotons;
    TTree* trigger;
    TTree* primaryParticleTrack;
    TTree* initialParticle;
    TTree* energyTrack;


    Float_t runIDBuffer;
    Float_t eventIDBuffer;
    Float_t detNumbBuffer;
    Float_t xPixelBuffer;
    Float_t yPixelBuffer;
    Float_t xPosBuffer;
    Float_t yPosBuffer;
    Float_t zPosBuffer;
    Float_t energyBuffer;
    Float_t wavelengthBuffer;
    Float_t timeBuffer;
    Float_t lengthBuffer;
    Float_t xMomBuffer;
    Float_t yMomBuffer;
    Float_t zMomBuffer;
    Float_t edepBuffer;

    Float_t gpsPositionX;
    Float_t gpsPositionY;
    Float_t gpsPositionZ;

    Float_t gpsDirectionX;
    Float_t gpsDirectionY;
    Float_t gpsDirectionZ;

    Int_t runIdBuffer;
    Int_t eventIdBuffer;
    Int_t trackIdBuffer;

    Int_t creatorProcessBuffer;
    Int_t parentIdBuffer;

    Float_t xBuffer;
    Float_t yBuffer;
    Float_t zBuffer;
    Float_t absTimeBuffer;

    Int_t materialBuffer;
    Int_t sectionNoBuffer;
    Float_t doseBuffer;
    Float_t attLengthBuffer;

    Float_t pxBuffer;
    Float_t pyBuffer;
    Float_t pzBuffer;


    Float_t vertexXBuffer;
    Float_t vertexYBuffer;
    Float_t vertexZBuffer;

    Float_t vertexPxBuffer;
    Float_t vertexPyBuffer;
    Float_t vertexPzBuffer;

    std::vector<Int_t> reflectionsAtMirror;
    std::vector<Int_t> reflectionsAtFibreSurface;
    std::vector<Int_t> reflectionsTotalAtCladCladInterface;
    std::vector<Int_t> reflectionsTotalAtCoreCladInterface;
    std::vector<Int_t> reflectionsFresnelAtCladCladInterface;
    std::vector<Int_t> reflectionsFresnelAtCoreCladInterface;

    std::vector<Int_t> refractionsAtCladCladInterface;
    std::vector<Int_t> refractionsAtCoreCladInterface;

    std::vector<Int_t> rayleighScatterings;

    Int_t reflMirrBuffer;
    Int_t reflSurfBuffer;
    Int_t reflTotalCladCladBuffer;
    Int_t reflTotalCoreCladBuffer;
    Int_t reflFresnelCladCladBuffer;
    Int_t reflFresnelCoreCladBuffer;

    Int_t refracCladCladBuffer;
    Int_t refracCoreCladBuffer;

    Int_t rayleighScatteringsBuffer;


    std::vector<Float_t> lengthInCore;
    std::vector<Float_t> lengthInInnerCladding;
    std::vector<Float_t> lengthInOuterCladding;

    Float_t lengthInCoreBuffer;
    Float_t lengthInInnerCladdingBuffer;
    Float_t lengthInOuterCladdingBuffer;
};

#endif
