#include "PFermiMomentumDD.h"
PFermiMomentumDD::PFermiMomentumDD(const Char_t *id, const Char_t *de, Int_t key) : 
    PFermiMomentum(id, de, key) {
};
PDistribution *PFermiMomentumDD::Clone(const char *) const {
    return new PFermiMomentumDD((const PFermiMomentumDD &)* this);
};
Bool_t PFermiMomentumDD::Init(void) {
    beam   = GetParticle("beam");
    target = GetParticle("target");
    parent = GetParticle("parent");
    if (!beam || !target) {
	Warning("Init", "<%s> beam or target not found", GetIdentifier());
	return kFALSE;
    }
    spectator1 = GetParticle("spectator");
    spectator2 = GetParticle("spectator");
    p1 = GetParticle("p1");
    p2 = GetParticle("p2");
    composite = GetParticle("composite");
    if (!composite) {
	Warning("Init", "<%s> composite not found", GetIdentifier());
	return kFALSE;
    }
    return kTRUE;
}
Bool_t PFermiMomentumDD::SampleMass(void) {
   
    PParticle participant1, participant2;
    Int_t pair1_is_beam = 0;
    
    
    if ((spectator1->ID() == 14) && (spectator2->ID() == 14)) {
	participant1.SetID(13);
	participant2.SetID(13);
	pair1_is_beam = 1; 
    } else if ((spectator1->ID() == 13) && (spectator2->ID() == 13)) {
	participant1.SetID(14);
	participant2.SetID(14);
	pair1_is_beam = 1; 
    } else if ((spectator1->ID() == 14) && (spectator2->ID() == 13)) {
	
	
	Double_t dummy = 0;
	if (beam->GetValue(P_SCATTER, &dummy)) 
	    pair1_is_beam = 1; 
	else if (!target->GetValue(P_SCATTER, &dummy)) {
	    
	    pair1_is_beam = (PUtils::sampleFlat() < 0.5 ? 0 : 1);
	}	
	participant1.SetID(13);
	participant2.SetID(14);
    } else if ((spectator1->ID() == 13) && (spectator2->ID() == 14)){
	
	
	Double_t dummy = 0;
	pair1_is_beam = 1; 
	if (target->GetValue(P_SCATTER, &dummy)) 
	    pair1_is_beam = 0; 
	else if (!beam->GetValue(P_SCATTER, &dummy)) {
	    
	    pair1_is_beam = (PUtils::sampleFlat() < 0.5 ? 0 : 1);
	}
	participant1.SetID(14);
	participant2.SetID(13);
    } else {
	Warning("SampleMass", "Unknown reaction");
    }
    
    Double_t massS, eS, eP, ptot, px, py, pz, t=-1., mdeut;
    
    while (t < 0.) {
	ptot  = SampleFermi(px,py,pz);                 
	massS = spectator1->M();                       
	eS = sqrt(ptot*ptot + massS*massS);            
	mdeut = makeStaticData()->GetParticleMass("d");
	t = pow(mdeut-massS,2) - 2.*mdeut*(eS-massS);  
    }
    if (t < 0.) {
	Warning("SampleMass", "Insufficient energy");
	return kTRUE;
    }
    eP = sqrt(ptot*ptot + t);         
    participant1.SetPxPyPzE(-px, -py, -pz, eP);  
    spectator1->SetPxPyPzE(px, py, pz, eS);      
     
    while (t < 0.) {
	ptot  = SampleFermi(px,py,pz);                 
	massS = spectator2->M();                       
	eS = sqrt(ptot*ptot + massS*massS);            
	mdeut = makeStaticData()->GetParticleMass("d");
	t = pow(mdeut-massS,2) - 2.*mdeut*(eS-massS);  
    }
    if (t < 0.) {
	Warning("SampleMass", "Insufficient energy");
	return kTRUE;
    }
    eP = sqrt(ptot*ptot + t);         
    participant2.SetPxPyPzE(-px,-py,-pz,eP);  
    spectator2->SetPxPyPzE(px,py,pz,eS);      
    
    
    if (pair1_is_beam) {
	
	participant1.Boost(beam->BoostVector()); 
	spectator1->Boost(beam->BoostVector());  
	participant2.Boost(target->BoostVector()); 
	spectator2->Boost(target->BoostVector());  
	if (participant2.ID() == p1->ID()) { 
	    *p1 = participant2;
	    *p2 = participant1;
	} else { 
	    *p2 = participant1;
	    *p1 = participant2;
	}
    } else {
	
	participant2.Boost(beam->BoostVector()); 
	spectator2->Boost(beam->BoostVector());  
	participant1.Boost(target->BoostVector()); 
	spectator1->Boost(target->BoostVector());  
	if (participant2.ID() == p1->ID()) { 
	    *p1 = participant2;
	    *p2 = participant1;
	} else  { 
	    *p2 = participant1;
	    *p1 = participant2;
	}
    }
    
    p1->Boost(-parent->BoostVector());
    p2->Boost(-parent->BoostVector());
    spectator1->Boost(-parent->BoostVector());
    spectator2->Boost(-parent->BoostVector());
    composite->Reconstruct(); 
    
    p1->Boost(parent->BoostVector());
    p2->Boost(parent->BoostVector());
    spectator1->SetW(parent->W());                  
    spectator2->SetW(parent->W());
    return kTRUE;
}
ClassImp(PFermiMomentumDD)