using namespace std;
#include <sstream>
#include <iostream>
#include <iomanip>
#include "PHadronDecay.h"
ClassImp(PHadronDecay)
PHadronDecay::PHadronDecay()  {
};
PHadronDecay::PHadronDecay(const Char_t *id, const Char_t *de, Int_t key) :
    PChannelModel(id, de, key) {
    if (is_channel < 0)
	Warning("PHadronDecay", "The model (%s) should be bound to CHANNELS only", de);
  
    
    Int_t tid[11];
    tid[0] = 10; 
    makeStaticData()->GetDecayModeByKey(key, tid); 
    
    parent_id   = makeStaticData()->GetDecayParentByKey(key);
    parent_g0   = makeStaticData()->GetParticleTotalWidth(parent_id);
    parent_mass = makeStaticData()->GetParticleMass(parent_id);
    if (tid[0] != 2) 
	Warning("PHadronDecay", "(%s):  Only 2 body decay", de);
    mass1 = makeStaticData()->GetParticleMass(tid[1]);
    mass2 = makeStaticData()->GetParticleMass(tid[2]);
    id1   = tid[1];
    id2   = tid[2];
    
    
    if (makeStaticData()->IsParticleMeson(parent_id) ||
	PData::IsDelta(parent_id)) {
	use_fixed_delta = 1;
	fixed_delta     = 0.09;
    } else 
	use_fixed_delta = 0;
    angular_l = (makeStaticData()->IsParticleMeson(parent_id)) ? 
	makeStaticData()->GetParticleSpin(parent_id)/2 : 
	PData::LPW(parent_id, id1, id2);
    if (!makeStaticData()->IsParticleMeson(parent_id)) 
	cutoff_l = 1;
    else 
	cutoff_l = 0; 
    if (makeStaticData()->IsParticleMeson(parent_id)) 
	use_m0_over_m = 1;
    else 
	use_m0_over_m = 0;
    if ((makeStaticData()->GetParticleID("D++") == parent_id) ||
	(makeStaticData()->GetParticleID("D+") == parent_id) ||
	(makeStaticData()->GetParticleID("D0") == parent_id) ||
	(makeStaticData()->GetParticleID("D-") == parent_id))
	use_m0_over_m = 1;
    
    cutoff_version = 0;
    version_flag |= VERSION_MASS_SAMPLING;  
    w0=makeStaticData()->GetDecayBR(is_channel); 
};
PDistribution *PHadronDecay::Clone(const char*) const {
    return new PHadronDecay((const PHadronDecay &)* this);
};
Bool_t PHadronDecay::Init(void) {
    
    return kTRUE;
};
Double_t PHadronDecay::EvalPar(const Double_t *x, const Double_t *) {
    return Eval(x[0]);
};
 
Double_t PHadronDecay::Eval(Double_t x, Double_t, Double_t, Double_t) const {
    Double_t res;
    Double_t mass[3];
    mass[0] = x; 
    mass[1] = mass1;
    mass[2] = mass2;
    if (draw_option == 0) {
	return ((PChannelModel*)this)->GetWeight(mass);
	
    } else if (draw_option == 1) {
	((PChannelModel*)this)->GetWidth(x,&res);
	return res;
    } else if (draw_option == 2) {
	((PChannelModel*)this)->GetBR(x,&res);
	return res;
    }
    return 0;
};
int PHadronDecay::GetDepth(int) {
    
    makeStaticData()->SetDecayEmin(is_channel, mass1+mass2);
    return 0; 
};
Bool_t PHadronDecay::SampleMass(void) {
    
    return kTRUE;
};
Bool_t PHadronDecay::SampleMass(Double_t *mass, Int_t *) {
    
    
    
    mass[1] = mass1;
    mass[2] = mass2;
    return kTRUE;
};
   
	
Bool_t PHadronDecay::GetWidth(Double_t mass, Double_t *width, Int_t) {
    if (makeStaticData()->GetPWidx(is_channel) == -1) {
	*width = parent_g0;
	return kFALSE;
    }
    *width = w0*HadronWidth(mass, mass1, mass2);
    return kTRUE;
}
    
double PHadronDecay::HadronWidth(const double &m, const double &ma, const double &mb) {
    
    
    
    
    
    
    
    
    double m0 = parent_mass, 
	ms = ma+mb, 
	md = m0-ms;
    
    if (m <= ms) return 0.;
    double qr2 = PKinematics::pcms2(m0, ma, mb),
	q2 = PKinematics::pcms2(m, ma, mb);
    if (qr2 == 0) 
	qr2 = 1;   
    double q = sqrt(q2/qr2);
    if (!id1) 
	return parent_g0*q*m0/m;  
    double delta2 = (use_fixed_delta) ? fixed_delta : md*md+0.25*parent_g0*parent_g0;
    double cutoff = (qr2 + delta2)/(q2 + delta2);
    if (angular_l) {
	q = pow(q,2*angular_l+1);
	if (cutoff_l) 
	    cutoff = pow(cutoff, angular_l+1);
    }
    if (cutoff_version == 1) {
	if (angular_l)
	    cutoff = (1.2)/(1+0.2*pow(q,2*angular_l));
	else
	    cutoff = (1.2)/(1+0);
    } else if (cutoff_version == 2) {
	cutoff = 1;
	cout << "no cutoff " << is_channel << endl;
	cout << "mass " << m << " res: " << q << endl;
    }
    q *= parent_g0*cutoff;
    return (use_m0_over_m) ? q*pow((m0/m),use_m0_over_m) : q;
}
ClassImp(PHadronDecay)