/////////////////////////////////////////////////////////////////////
//
// Decay Model of Hadron -> 3 unstable hadrons
// 
//
//                                  Author:  I. Froehlich
/////////////////////////////////////////////////////////////////////


using namespace std;
#include <sstream>
#include <iostream>
#include <iomanip>

#include "PHadronDecayM3.h"


ClassImp(PHadronDecayM3)

PHadronDecayM3::PHadronDecayM3() {
};

PHadronDecayM3::PHadronDecayM3(const Char_t *id, const Char_t *de, Int_t key) :
    PChannelModel(id, de, key) {
    if (is_channel < 0)
	Warning("PHadronDecayM3", "The model (%s) should be bound to CHANNELS only", de);
  
    //Get particles
    Int_t tid[11];
    tid[0] = 10; 
    makeStaticData()->GetDecayModeByKey(primary_key, tid); // retrieve current mode info

    //Parent ALWAYS important (also for the inherited classes)
    parent_id   = makeStaticData()->GetDecayParentByKey(primary_key);
    parent_mass = makeStaticData()->GetParticleMass(parent_id);

    if (tid[0] != 3) 
	Warning("PHadronDecayM3", "(%s):  Only 3 body decay", de);

    mass1 = makeStaticData()->GetParticleMass(tid[1]);
    mass2 = makeStaticData()->GetParticleMass(tid[2]);
    mass3 = makeStaticData()->GetParticleMass(tid[3]);
    id1   = tid[1];
    id2   = tid[2];
    id3   = tid[3];
    didx1 = -1;
    didx2 = -1;
    didx3 = -1;
};

PDistribution *PHadronDecayM3::Clone(const char *) const {
    return new PHadronDecayM3((const PHadronDecayM3 &)* this);
};

Bool_t PHadronDecayM3::Init(void) {
    //Init function called once for each PChannel

    //looking for parent. This is mandatory
    parent = GetParticle("parent");
    if (!parent) {
	Warning("Init", "Parent not found");
	return kFALSE;
    }

    //getting 3 daughters
    daughter1 = GetParticle(makeStaticData()->GetParticleName(id1));
    daughter2 = GetParticle(makeStaticData()->GetParticleName(id2));
    daughter3 = GetParticle(makeStaticData()->GetParticleName(id3));

    return kTRUE;
}

Bool_t PHadronDecayM3::Prepare(void) {
    //Things which might change during the eventloop
    
    didx1 = daughter1->GetDecayModeIndex(1);
    didx2 = daughter2->GetDecayModeIndex(1);
    didx3 = daughter3->GetDecayModeIndex(1);

    return kTRUE;
}
 
Double_t PHadronDecayM3::Eval(Double_t x, Double_t, Double_t, Double_t) const {
    Double_t res;
    Double_t mass[4];
    mass[0] = x; 
    mass[1] = mass1;
    mass[2] = mass2;
    mass[3] = mass3;

    if (draw_option == 0) {
	return ((PChannelModel*)this)->GetWeight(mass);
	//return res;
    } 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 PHadronDecayM3::GetDepth(int i) {
    //check if we have models
    //This also initializes the sub-models

    Int_t a1=0, a2=0, a3=0;
    model1 = makeDynamicData()->GetParticleModel(id1);
    model2 = makeDynamicData()->GetParticleModel(id2);
    model3 = makeDynamicData()->GetParticleModel(id3);
    if (model1) a1 = model1->GetDepth(i);
    if (model2) a2 = model2->GetDepth(i);
    if (model3) a3 = model3->GetDepth(i);

    makeStaticData()->SetDecayEmin(is_channel, mass1+mass2+mass3);

    return TMath::Max(a1+1, TMath::Max(a2+1,a3+1)); 
}

void PHadronDecayM3::SubPrint(Int_t) const {
    //Print sub-models
    
    if (model1) {
	cout << " ";
	cout << model1->GetDescription();
    }
    if (model2) {
	cout << " ";
	cout << model2->GetDescription();
    }
    if (model3) {
	cout << " ";
	cout << model3->GetDescription();
    }
}

Bool_t PHadronDecayM3::SampleMass(void) {
    //Mass-sampling wrapper

    Double_t mass[4];
    Int_t didx[4];
    didx[1] = didx1;
    didx[2] = didx2;
    didx[3] = didx3;
    mass[0] = parent->M();
    Bool_t ret = SampleMass(mass,didx);
    daughter1->SetM(mass[1]);
    daughter2->SetM(mass[2]);
    daughter3->SetM(mass[3]);
    return ret;
};

Bool_t PHadronDecayM3::SampleMass(Double_t *mass, Int_t *didx) {
    //Samples the mass of 3 decay products
    //We check if there is a primary model for each
    //decay product, if not, set the mass to the nominal
    //value

    int didx_local1 = -1;
    int didx_local2 = -1;
    int didx_local3 = -1;
    if (didx) didx_local1 = didx[1];
    if (didx) didx_local2 = didx[2];
    if (didx) didx_local3 = didx[3];

    int counter = 0;
    Double_t old_max = 0.;
    PChannelModel *unstable = NULL;

    mass[1] = mass1;
    mass[2] = mass2;
    mass[3] = mass3;

#if 0
    //exclude forbidden region
    if (model1 && !model2 && !model3) {
	unstable = model1;
	old_max=model1->GetMax();
	model1->SetMax(mass[0] - mass[2] - mass[3] );
	model1->ClearIntegral();
    } else if (!model1 && model2 && !model3) {
	unstable = model2;
	old_max=model2->GetMax();
	model2->SetMax(mass[0] - mass[1] - mass[3] );
	model2->ClearIntegral();
    } else if (!model1 && !model2 && model3) {
	unstable = model3;
	old_max=model3->GetMax();
	model3->SetMax(mass[0] - mass[1] - mass[2] );
	model3->ClearIntegral();
    } 
#endif

 repeat1:

    counter++;

    if (model1) model1->SampleMass(&mass[1], &didx_local1);
    if (model2) model2->SampleMass(&mass[2], &didx_local2);
    if (model3) model3->SampleMass(&mass[3], &didx_local3);

    if ((mass[0] < (mass[1] + mass[2] + mass[3])) && (counter <1000)) {
	goto repeat1;
    } else if (counter >= 1000){
	Warning("SampleMass", "Sampling aborted, resonance mass distribution too large?");
	if (unstable) unstable->SetMax(old_max);
	return kFALSE;
    }

    //Convolute with 3body phase space
    double m12min2    = (mass[1]+mass[2])*(mass[1]+mass[2]);
    double m12max2    = (mass[0]-mass[3])*(mass[0]-mass[3]);
    double m23min2    = (mass[2]+mass[3])*(mass[2]+mass[3]);
    double m23max2    = (mass[0]-mass[1])*(mass[0]-mass[1]);
    double phaseSpace = (m12max2-m12min2)*(m23max2-m23min2);
    m12min2 = pow(PData::LMass(id1)+PData::LMass(id2), 2);
    m12max2 = pow(mass[0]-PData::LMass(id3),2);
    m23min2 = pow(PData::LMass(id2)+PData::LMass(id3), 2);
    m23max2 = pow(mass[0]-PData::LMass(id1),2);
    double phaseSpaceMax = (m12max2-m12min2)*(m23max2-m23min2);
    //if ( (pow(phaseSpace/phaseSpaceMax,0.90)<PUtils::sampleFlat())  && (counter <1000) ) {
    if (((phaseSpace/phaseSpaceMax) <PUtils::sampleFlat())  && (counter <1000) ) {
	goto repeat1;
    } 	else if (counter >= 1000) {
	Warning("SampleMass", "Sampling aborted, resonance mass too large?");
	if (unstable) unstable->SetMax(old_max);
	return kFALSE;
    }
 
    if (unstable) unstable->SetMax(old_max);
    return kTRUE;
};

Bool_t PHadronDecayM3::GetWidth(Double_t mass, Double_t *width, Int_t) {
    
    double q_value      = mass-(mass1+mass2+mass3);
    double q_value_pole = parent_mass-(mass1+mass2+mass3);
    
    *width = (q_value/q_value_pole)*(q_value/q_value_pole);

    //*width=makeStaticData()->GetDecayPartialWidth(is_channel);
    return kTRUE;
}

Double_t PHadronDecayM3::GetWeight(void) {
    Double_t mass[4];
    mass[0] = parent->M();
    mass[1] = daughter1->M();
    mass[2] = daughter2->M();
    mass[3] = daughter3->M();
    Int_t didx[4];
    didx[1] = didx1;
    didx[2] = didx2;
    didx[3] = didx3;

    //Convolute with 3body phase space
    double m12min2    = (mass[1]+mass[2])*(mass[1]+mass[2]);
    double m12max2    = (mass[0]-mass[3])*(mass[0]-mass[3]);
    double m23min2    = (mass[2]+mass[3])*(mass[2]+mass[3]);
    double m23max2    = (mass[0]-mass[1])*(mass[0]-mass[1]);
    double phaseSpace = (m12max2-m12min2)*(m23max2-m23min2);
    m12min2 = pow(PData::LMass(id1)+PData::LMass(id2), 2);
    m12max2 = pow(mass[0]-PData::LMass(id3), 2);
    m23min2 = pow(PData::LMass(id2)+PData::LMass(id3), 2);
    m23max2 = pow(mass[0]-PData::LMass(id1), 2);
    double phaseSpaceMax = (m12max2-m12min2)*(m23max2-m23min2);

    return GetWeight(mass,didx)*(phaseSpace/phaseSpaceMax); 
}

Double_t PHadronDecayM3::GetWeight(Double_t *mass, Int_t *didx) {
    //Convolution of all 3 masses
    int didx_local1 = -1;
    int didx_local2 = -1;
    int didx_local3 = -1;
    if (didx) didx_local1 = didx[1];
    if (didx) didx_local2 = didx[2];
    if (didx) didx_local3 = didx[3];

    Double_t weight = 1.;
    if (model1) weight*=model1->GetWeight(&mass[1], &didx_local1);
    if (model2) weight*=model2->GetWeight(&mass[2], &didx_local2);
    if (model3) weight*=model3->GetWeight(&mass[3], &didx_local3);
    return weight;
}

ClassImp(PHadronDecayM3)
 PHadronDecayM3.cc:1
 PHadronDecayM3.cc:2
 PHadronDecayM3.cc:3
 PHadronDecayM3.cc:4
 PHadronDecayM3.cc:5
 PHadronDecayM3.cc:6
 PHadronDecayM3.cc:7
 PHadronDecayM3.cc:8
 PHadronDecayM3.cc:9
 PHadronDecayM3.cc:10
 PHadronDecayM3.cc:11
 PHadronDecayM3.cc:12
 PHadronDecayM3.cc:13
 PHadronDecayM3.cc:14
 PHadronDecayM3.cc:15
 PHadronDecayM3.cc:16
 PHadronDecayM3.cc:17
 PHadronDecayM3.cc:18
 PHadronDecayM3.cc:19
 PHadronDecayM3.cc:20
 PHadronDecayM3.cc:21
 PHadronDecayM3.cc:22
 PHadronDecayM3.cc:23
 PHadronDecayM3.cc:24
 PHadronDecayM3.cc:25
 PHadronDecayM3.cc:26
 PHadronDecayM3.cc:27
 PHadronDecayM3.cc:28
 PHadronDecayM3.cc:29
 PHadronDecayM3.cc:30
 PHadronDecayM3.cc:31
 PHadronDecayM3.cc:32
 PHadronDecayM3.cc:33
 PHadronDecayM3.cc:34
 PHadronDecayM3.cc:35
 PHadronDecayM3.cc:36
 PHadronDecayM3.cc:37
 PHadronDecayM3.cc:38
 PHadronDecayM3.cc:39
 PHadronDecayM3.cc:40
 PHadronDecayM3.cc:41
 PHadronDecayM3.cc:42
 PHadronDecayM3.cc:43
 PHadronDecayM3.cc:44
 PHadronDecayM3.cc:45
 PHadronDecayM3.cc:46
 PHadronDecayM3.cc:47
 PHadronDecayM3.cc:48
 PHadronDecayM3.cc:49
 PHadronDecayM3.cc:50
 PHadronDecayM3.cc:51
 PHadronDecayM3.cc:52
 PHadronDecayM3.cc:53
 PHadronDecayM3.cc:54
 PHadronDecayM3.cc:55
 PHadronDecayM3.cc:56
 PHadronDecayM3.cc:57
 PHadronDecayM3.cc:58
 PHadronDecayM3.cc:59
 PHadronDecayM3.cc:60
 PHadronDecayM3.cc:61
 PHadronDecayM3.cc:62
 PHadronDecayM3.cc:63
 PHadronDecayM3.cc:64
 PHadronDecayM3.cc:65
 PHadronDecayM3.cc:66
 PHadronDecayM3.cc:67
 PHadronDecayM3.cc:68
 PHadronDecayM3.cc:69
 PHadronDecayM3.cc:70
 PHadronDecayM3.cc:71
 PHadronDecayM3.cc:72
 PHadronDecayM3.cc:73
 PHadronDecayM3.cc:74
 PHadronDecayM3.cc:75
 PHadronDecayM3.cc:76
 PHadronDecayM3.cc:77
 PHadronDecayM3.cc:78
 PHadronDecayM3.cc:79
 PHadronDecayM3.cc:80
 PHadronDecayM3.cc:81
 PHadronDecayM3.cc:82
 PHadronDecayM3.cc:83
 PHadronDecayM3.cc:84
 PHadronDecayM3.cc:85
 PHadronDecayM3.cc:86
 PHadronDecayM3.cc:87
 PHadronDecayM3.cc:88
 PHadronDecayM3.cc:89
 PHadronDecayM3.cc:90
 PHadronDecayM3.cc:91
 PHadronDecayM3.cc:92
 PHadronDecayM3.cc:93
 PHadronDecayM3.cc:94
 PHadronDecayM3.cc:95
 PHadronDecayM3.cc:96
 PHadronDecayM3.cc:97
 PHadronDecayM3.cc:98
 PHadronDecayM3.cc:99
 PHadronDecayM3.cc:100
 PHadronDecayM3.cc:101
 PHadronDecayM3.cc:102
 PHadronDecayM3.cc:103
 PHadronDecayM3.cc:104
 PHadronDecayM3.cc:105
 PHadronDecayM3.cc:106
 PHadronDecayM3.cc:107
 PHadronDecayM3.cc:108
 PHadronDecayM3.cc:109
 PHadronDecayM3.cc:110
 PHadronDecayM3.cc:111
 PHadronDecayM3.cc:112
 PHadronDecayM3.cc:113
 PHadronDecayM3.cc:114
 PHadronDecayM3.cc:115
 PHadronDecayM3.cc:116
 PHadronDecayM3.cc:117
 PHadronDecayM3.cc:118
 PHadronDecayM3.cc:119
 PHadronDecayM3.cc:120
 PHadronDecayM3.cc:121
 PHadronDecayM3.cc:122
 PHadronDecayM3.cc:123
 PHadronDecayM3.cc:124
 PHadronDecayM3.cc:125
 PHadronDecayM3.cc:126
 PHadronDecayM3.cc:127
 PHadronDecayM3.cc:128
 PHadronDecayM3.cc:129
 PHadronDecayM3.cc:130
 PHadronDecayM3.cc:131
 PHadronDecayM3.cc:132
 PHadronDecayM3.cc:133
 PHadronDecayM3.cc:134
 PHadronDecayM3.cc:135
 PHadronDecayM3.cc:136
 PHadronDecayM3.cc:137
 PHadronDecayM3.cc:138
 PHadronDecayM3.cc:139
 PHadronDecayM3.cc:140
 PHadronDecayM3.cc:141
 PHadronDecayM3.cc:142
 PHadronDecayM3.cc:143
 PHadronDecayM3.cc:144
 PHadronDecayM3.cc:145
 PHadronDecayM3.cc:146
 PHadronDecayM3.cc:147
 PHadronDecayM3.cc:148
 PHadronDecayM3.cc:149
 PHadronDecayM3.cc:150
 PHadronDecayM3.cc:151
 PHadronDecayM3.cc:152
 PHadronDecayM3.cc:153
 PHadronDecayM3.cc:154
 PHadronDecayM3.cc:155
 PHadronDecayM3.cc:156
 PHadronDecayM3.cc:157
 PHadronDecayM3.cc:158
 PHadronDecayM3.cc:159
 PHadronDecayM3.cc:160
 PHadronDecayM3.cc:161
 PHadronDecayM3.cc:162
 PHadronDecayM3.cc:163
 PHadronDecayM3.cc:164
 PHadronDecayM3.cc:165
 PHadronDecayM3.cc:166
 PHadronDecayM3.cc:167
 PHadronDecayM3.cc:168
 PHadronDecayM3.cc:169
 PHadronDecayM3.cc:170
 PHadronDecayM3.cc:171
 PHadronDecayM3.cc:172
 PHadronDecayM3.cc:173
 PHadronDecayM3.cc:174
 PHadronDecayM3.cc:175
 PHadronDecayM3.cc:176
 PHadronDecayM3.cc:177
 PHadronDecayM3.cc:178
 PHadronDecayM3.cc:179
 PHadronDecayM3.cc:180
 PHadronDecayM3.cc:181
 PHadronDecayM3.cc:182
 PHadronDecayM3.cc:183
 PHadronDecayM3.cc:184
 PHadronDecayM3.cc:185
 PHadronDecayM3.cc:186
 PHadronDecayM3.cc:187
 PHadronDecayM3.cc:188
 PHadronDecayM3.cc:189
 PHadronDecayM3.cc:190
 PHadronDecayM3.cc:191
 PHadronDecayM3.cc:192
 PHadronDecayM3.cc:193
 PHadronDecayM3.cc:194
 PHadronDecayM3.cc:195
 PHadronDecayM3.cc:196
 PHadronDecayM3.cc:197
 PHadronDecayM3.cc:198
 PHadronDecayM3.cc:199
 PHadronDecayM3.cc:200
 PHadronDecayM3.cc:201
 PHadronDecayM3.cc:202
 PHadronDecayM3.cc:203
 PHadronDecayM3.cc:204
 PHadronDecayM3.cc:205
 PHadronDecayM3.cc:206
 PHadronDecayM3.cc:207
 PHadronDecayM3.cc:208
 PHadronDecayM3.cc:209
 PHadronDecayM3.cc:210
 PHadronDecayM3.cc:211
 PHadronDecayM3.cc:212
 PHadronDecayM3.cc:213
 PHadronDecayM3.cc:214
 PHadronDecayM3.cc:215
 PHadronDecayM3.cc:216
 PHadronDecayM3.cc:217
 PHadronDecayM3.cc:218
 PHadronDecayM3.cc:219
 PHadronDecayM3.cc:220
 PHadronDecayM3.cc:221
 PHadronDecayM3.cc:222
 PHadronDecayM3.cc:223
 PHadronDecayM3.cc:224
 PHadronDecayM3.cc:225
 PHadronDecayM3.cc:226
 PHadronDecayM3.cc:227
 PHadronDecayM3.cc:228
 PHadronDecayM3.cc:229
 PHadronDecayM3.cc:230
 PHadronDecayM3.cc:231
 PHadronDecayM3.cc:232
 PHadronDecayM3.cc:233
 PHadronDecayM3.cc:234
 PHadronDecayM3.cc:235
 PHadronDecayM3.cc:236
 PHadronDecayM3.cc:237
 PHadronDecayM3.cc:238
 PHadronDecayM3.cc:239
 PHadronDecayM3.cc:240
 PHadronDecayM3.cc:241
 PHadronDecayM3.cc:242
 PHadronDecayM3.cc:243
 PHadronDecayM3.cc:244
 PHadronDecayM3.cc:245
 PHadronDecayM3.cc:246
 PHadronDecayM3.cc:247
 PHadronDecayM3.cc:248
 PHadronDecayM3.cc:249
 PHadronDecayM3.cc:250
 PHadronDecayM3.cc:251
 PHadronDecayM3.cc:252
 PHadronDecayM3.cc:253
 PHadronDecayM3.cc:254
 PHadronDecayM3.cc:255
 PHadronDecayM3.cc:256
 PHadronDecayM3.cc:257
 PHadronDecayM3.cc:258
 PHadronDecayM3.cc:259
 PHadronDecayM3.cc:260
 PHadronDecayM3.cc:261
 PHadronDecayM3.cc:262
 PHadronDecayM3.cc:263
 PHadronDecayM3.cc:264
 PHadronDecayM3.cc:265
 PHadronDecayM3.cc:266
 PHadronDecayM3.cc:267
 PHadronDecayM3.cc:268
 PHadronDecayM3.cc:269
 PHadronDecayM3.cc:270
 PHadronDecayM3.cc:271
 PHadronDecayM3.cc:272
 PHadronDecayM3.cc:273
 PHadronDecayM3.cc:274
 PHadronDecayM3.cc:275
 PHadronDecayM3.cc:276
 PHadronDecayM3.cc:277
 PHadronDecayM3.cc:278
 PHadronDecayM3.cc:279
 PHadronDecayM3.cc:280
 PHadronDecayM3.cc:281
 PHadronDecayM3.cc:282
 PHadronDecayM3.cc:283
 PHadronDecayM3.cc:284
 PHadronDecayM3.cc:285
 PHadronDecayM3.cc:286
 PHadronDecayM3.cc:287
 PHadronDecayM3.cc:288