// $Id: PamVMCStack.cxx,v 1.0 2007/06/03 
//
// Class PamVMCStack

#include <TParticle.h>
#include <TClonesArray.h>
#include <TError.h>
#include <Riostream.h>

#include "PamVMCStack.h"

ClassImp(PamVMCStack)

PamVMCStack::PamVMCStack(Int_t size)
  : fParticles(0),
    fCurrentTrack(-1),
    fNPrimary(0)
{
  fParticles = new TClonesArray("TParticle", size);
}

PamVMCStack::PamVMCStack()
  : fParticles(0),
    fCurrentTrack(-1),
    fNPrimary(0)
{


}

PamVMCStack::~PamVMCStack() 
{

  if (fParticles) fParticles->Delete();
  delete fParticles;
}


void  PamVMCStack::PushTrack(Int_t toBeDone, Int_t parent, Int_t pdg,
  	                 Double_t px, Double_t py, Double_t pz, Double_t e,
  		         Double_t vx, Double_t vy, Double_t vz, Double_t tof,
		         Double_t polx, Double_t poly, Double_t polz,
		         TMCProcess mech, Int_t& /*ntr*/, Double_t weight,
		         Int_t is) 
{
// Creates a new particle with specified properties,
// adds it to the particles array (fParticles) and if not done to the 
// stack (fStack).
// Use TParticle::fMother[1] to store Track ID. 

  const Int_t kFirstDaughter=-1;
  const Int_t kLastDaughter=-1;
  
  TClonesArray& particlesRef = *fParticles;
  Int_t trackId = GetNtrack();
  TParticle* particle
    = new(particlesRef[trackId]) 
      TParticle(pdg, is, parent, trackId, kFirstDaughter, kLastDaughter,
		px, py, pz, e, vx, vy, vz, tof);
   
  particle->SetPolarisation(polx, poly, polz);
  particle->SetWeight(weight);
  particle->SetUniqueID(mech);

  if (parent<0) fNPrimary++;  
    
  if (toBeDone) fStack.push(particle);  
}			 

TParticle* PamVMCStack::PopNextTrack(Int_t& itrack)
{
// Gets next particle for tracking from the stack.

  itrack = -1;
  if  (fStack.empty()) return 0;
		      
  TParticle* particle = fStack.top();
  fStack.pop();

  if (!particle) return 0;  
  
  fCurrentTrack = particle->GetSecondMother();
  itrack = fCurrentTrack;
  
  return particle;
}    

TParticle* PamVMCStack::PopPrimaryForTracking(Int_t i)
{
// Returns i-th particle in fParticles.


  if (i < 0 || i >= fNPrimary)
    Fatal("GetPrimaryForTracking", "Index out of range"); 
  
  return (TParticle*)fParticles->At(i);
}     

void PamVMCStack::Print(Option_t* /*option*/) const 
{
// Prints info for all particles.

  cout << "PamVMCStack Info  " << endl;
  cout << "Total number of particles:   " <<  GetNtrack() << endl;
  cout << "Number of primary particles: " <<  GetNprimary() << endl;

  for (Int_t i=0; i<GetNtrack(); i++)
    GetParticle(i)->Print();
}

void PamVMCStack::Reset()
{
// Deletes contained particles, resets particles array and stack.

  fCurrentTrack = -1;
  fNPrimary = 0;
  fParticles->Clear();
}       

void  PamVMCStack::SetCurrentTrack(Int_t track) 
{
// Sets the current track to a given value.

  fCurrentTrack = track;
}     

Int_t  PamVMCStack::GetNtrack() const 
{
// Returns the number of all tracks.

  return fParticles->GetEntriesFast();
}  

Int_t  PamVMCStack::GetNprimary() const 
{
// Returns the number of primary tracks.

  return fNPrimary;
}  

TParticle*  PamVMCStack::GetCurrentTrack() const 
{
// Returns the current track parent ID.

  TParticle* current = GetParticle(fCurrentTrack);

  if (!current)    
    Warning("GetCurrentTrack", "Current track not found in the stack");

  return current;
}  

Int_t  PamVMCStack::GetCurrentTrackNumber() const 
{
// Returns the current track ID.

  return fCurrentTrack;
}  

Int_t  PamVMCStack::GetCurrentParentTrackNumber() const 
{
// Returns the current track parent ID.

  TParticle* current = GetCurrentTrack();

  if (current) 
    return current->GetFirstMother();
  else 
    return -1;
}  

TParticle*  PamVMCStack::GetParticle(Int_t id) const
{
// Returns id-th particle in fParticles.

  if (id < 0 || id >= fParticles->GetEntriesFast())
    Fatal("GetParticle", "Index out of range"); 
   
  return (TParticle*)fParticles->At(id);
}


