using namespace std;
#include <sstream>
#include <iostream>
#include <iomanip>
#include "PComplexBreitWigner.h"
ClassImp(PComplexBreitWigner)
PComplexBreitWigner::PComplexBreitWigner() {
};
PComplexBreitWigner::PComplexBreitWigner(const Char_t *id, const Char_t *de, Int_t key) :
    PBreitWigner(id, de, key) {
    readModesDone   = 0;
    readModelsDone  = 0;
    updateAmplitude = 0;
    mr = makeStaticData()->GetParticleMassByKey(key);
};
PDistribution* PComplexBreitWigner::Clone(const char *) const {
    return new PComplexBreitWigner((const PComplexBreitWigner &)* this);
};
Bool_t PComplexBreitWigner::SampleMass(Double_t *mass, Int_t *didx) {
    
    
    if (didx) 
	didx_option = didx[0];
    else
	didx_option = -1;
    mass[0] = this->GetRandom();
    return kTRUE;
};
Double_t PComplexBreitWigner::GetWeight(Double_t *mass, Int_t *didx) {
    return GetAmplitude(mass, didx).Rho2();
};
void PComplexBreitWigner::ReadModes(void) {
    if (readModesDone) return;
    
    
    Int_t listkey = -1;
    num_decaychannels = 0;
    while (makeDataBase()->MakeListIterator(primary_key, "pnmodes", "link", &listkey)) {
	
	int_index[num_decaychannels] = makeStaticData()->GetDecayIdxByKey(listkey);
	num_terms[num_decaychannels] = 0;
	
	
	int_phase[num_decaychannels][0] = 0;
	int_ampl[num_decaychannels][0]  = 1;
	
	num_decaychannels++;
	if (num_decaychannels == COMPLEX_MAX_DECAYCHANNELS) {
	    Warning("ReadModes", "COMPLEX_MAX_DECAYCHANNELS reached");
	    listkey=-1;
	}
    } 
    readModesDone = 1;
}
void PComplexBreitWigner::AddAmplitude(int idx, double ampl, double phase) {
    ReadModes();
    
    int found_idx = -1;
    for (int i=0; i<num_decaychannels; i++) 
	if (int_index[i] == idx) 
	    found_idx = i;
    if (found_idx < 0) {
	Warning("AddAmplitude:", "idx %i is not a valid decay index for particle %i", idx, is_pid);
	return;
    }
    int_phase[found_idx][0] = phase;
    int_ampl[found_idx][0]  = ampl;
};
void PComplexBreitWigner::AddInterference(int idx, int key, int didx, double ampl, double phase) {
    
    
    
    
    
    ReadModes();
    
    int found_idx = -1;
    for (int i=0; i<num_decaychannels; i++) 
	if (int_index[i] == idx) 
	    found_idx = i;
    if (found_idx < 0) {
	Warning("AddInterference", "idx %i is not a valid decay index for particle %i", idx, is_pid);
	return;
    }
    if (num_terms[found_idx] == COMPLEX_MAX_TERMS) {
	Warning("AddInterference", "COMPLEX_MAX_TERMS reached");
	return;
    }
    num_terms[found_idx]++;
    int_didx[found_idx][num_terms[found_idx]]  = didx;
    int_key[found_idx][num_terms[found_idx]]   = key;
    int_phase[found_idx][num_terms[found_idx]] = phase;
    int_ampl[found_idx][num_terms[found_idx]]  = ampl;
};
Double_t PComplexBreitWigner::EvalPar(const Double_t *x, const Double_t *params) {
    if (params) {
	draw_option = (int)params[0];
	didx_option = (int)params[1];
	if (updateAmplitude) {
	    int found_idx = -1;	    
	    
	    for (int i=0; i<num_decaychannels; i++) 
		if (int_index[i] == didx_option) 
		    found_idx = i;
	    if (found_idx >= 0) {
		int_phase[found_idx][1] = params[3];
		int_ampl[found_idx][1]  = params[2];}
	}
    }
    return Eval(x[0]);
};
 
Double_t PComplexBreitWigner::Eval(Double_t x, Double_t, Double_t, Double_t) const {
    Double_t res;
    Double_t my_x[11];
    Int_t my_didx_option[11];
    my_x[0] = x;
    my_didx_option[0] = didx_option;
    if (draw_option == 0) {
	return ((PChannelModel*)this)->GetWeight(my_x, my_didx_option);
	
    }
    if (draw_option == 1) {
	((PChannelModel*)this)->GetWidth(x, &res, didx_option);
	return res;
    }
    if (draw_option == 2) {
	((PChannelModel*)this)->GetBR(x, &res);
	return res;
    }
    if (draw_option == 3) {
	return ((PChannelModel*)this)->GetAmplitude(my_x, my_didx_option).Re();
    }
    if (draw_option == 4) {
	return ((PChannelModel*)this)->GetAmplitude(my_x, my_didx_option).Im();
    }
    return 0;
};
void PComplexBreitWigner::ReadModels(void) {
    if (readModelsDone) return;
    
    for (int i=0; i<num_decaychannels; i++) {
	
	for (int j=1; j<=num_terms[i]; j++) {
	    TObject *t_result;
	    if (makeDataBase()->GetParamTObj (int_key[i][j], "model", &t_result))
		p[i][j] = (PChannelModel*)t_result;
	    else {
		p[i][j] = NULL;	
		Warning("ReadModels", "No term model found: this will not work");
	    }
	    p[i][j] = (PChannelModel*)t_result;
	}
    }
    readModelsDone = 1;
};
TComplex PComplexBreitWigner::GetAmplitudeLocal(Double_t *mass, Int_t num) {
    
    int didx_local = int_index[num];
    double m = mass[0],
	m2 = m*m, 	
	mm = mr*mr-m2;
    global_weight_scaling = makeDynamicData()->GetParticleScalingFactor(is_pid);
    double wmt = 1.;
    if (!GetWidth(m, &width)) return -1;
 
    double partial_width;
    if (didx_local >= 0) {
	if (!GetWidth(m, &partial_width, didx_local)) return -1;
	
	
    } else 
	partial_width = width;
    TComplex denom(mm, m*width);
    
    TComplex numerator(m*sqrt(partial_width*global_weight_scaling*wmt), 0);
    
    numerator /= denom;
    TComplex ampl(int_ampl[num][0], int_phase[num][0], kTRUE); 
    numerator *= ampl;
    
    
    
    TComplex interference(0, 0);
    for (int i=1; i<=num_terms[num]; i++) {
	TComplex interference_term(int_ampl[num][i], int_phase[num][i], kTRUE);
	if (p[num][i]) {
	    interference_term *= p[num][i]->GetAmplitude(mass, &int_didx[num][i]);
	} else {
	    Warning("GetAmplitudeLocal", "No model found");
	}
	interference+=interference_term;
    }
    if (num_terms[num])
	return numerator+interference;
    return numerator;
};
TComplex PComplexBreitWigner::GetAmplitude(Double_t *mass, Int_t *didx) {
    ReadModes();
    ReadModels();
    double weight  = 0;
    int didx_local = -1;
    if (didx) didx_local = didx[0];
    
    for (int i=0; i<num_decaychannels; i++) {
	if (didx_local < 0)
	    weight += GetAmplitudeLocal(mass, i).Rho();
	else if (didx_local == int_index[i])
	    return GetAmplitudeLocal(mass, i);
    }
    TComplex ampl(weight, 0);
    return ampl;
};
void PComplexBreitWigner::Print(const Option_t *) const {
    
    for (int i=0; i<num_decaychannels; i++) {
	
	cout << "Num:" << i << " Didx: " << int_index[i] << endl; 
	for (int j=1; j<=num_terms[i]; j++) {
	    cout << " Term: " << j << endl; 
	}
    }
}
 PComplexBreitWigner.cc:10  PComplexBreitWigner.cc:11  PComplexBreitWigner.cc:12  PComplexBreitWigner.cc:13  PComplexBreitWigner.cc:14  PComplexBreitWigner.cc:15  PComplexBreitWigner.cc:16  PComplexBreitWigner.cc:17  PComplexBreitWigner.cc:18  PComplexBreitWigner.cc:19  PComplexBreitWigner.cc:20  PComplexBreitWigner.cc:21  PComplexBreitWigner.cc:22  PComplexBreitWigner.cc:23  PComplexBreitWigner.cc:24  PComplexBreitWigner.cc:25  PComplexBreitWigner.cc:26  PComplexBreitWigner.cc:27  PComplexBreitWigner.cc:28  PComplexBreitWigner.cc:29  PComplexBreitWigner.cc:30  PComplexBreitWigner.cc:31  PComplexBreitWigner.cc:32  PComplexBreitWigner.cc:33  PComplexBreitWigner.cc:34  PComplexBreitWigner.cc:35  PComplexBreitWigner.cc:36  PComplexBreitWigner.cc:37  PComplexBreitWigner.cc:38  PComplexBreitWigner.cc:39  PComplexBreitWigner.cc:40  PComplexBreitWigner.cc:41  PComplexBreitWigner.cc:42  PComplexBreitWigner.cc:43  PComplexBreitWigner.cc:44  PComplexBreitWigner.cc:45  PComplexBreitWigner.cc:46  PComplexBreitWigner.cc:47  PComplexBreitWigner.cc:48  PComplexBreitWigner.cc:49  PComplexBreitWigner.cc:50  PComplexBreitWigner.cc:51  PComplexBreitWigner.cc:52  PComplexBreitWigner.cc:53  PComplexBreitWigner.cc:54  PComplexBreitWigner.cc:55  PComplexBreitWigner.cc:56  PComplexBreitWigner.cc:57  PComplexBreitWigner.cc:58  PComplexBreitWigner.cc:59  PComplexBreitWigner.cc:60  PComplexBreitWigner.cc:61  PComplexBreitWigner.cc:62  PComplexBreitWigner.cc:63  PComplexBreitWigner.cc:64  PComplexBreitWigner.cc:65  PComplexBreitWigner.cc:66  PComplexBreitWigner.cc:67  PComplexBreitWigner.cc:68  PComplexBreitWigner.cc:69  PComplexBreitWigner.cc:70  PComplexBreitWigner.cc:71  PComplexBreitWigner.cc:72  PComplexBreitWigner.cc:73  PComplexBreitWigner.cc:74  PComplexBreitWigner.cc:75  PComplexBreitWigner.cc:76  PComplexBreitWigner.cc:77  PComplexBreitWigner.cc:78  PComplexBreitWigner.cc:79  PComplexBreitWigner.cc:80  PComplexBreitWigner.cc:81  PComplexBreitWigner.cc:82  PComplexBreitWigner.cc:83  PComplexBreitWigner.cc:84  PComplexBreitWigner.cc:85  PComplexBreitWigner.cc:86  PComplexBreitWigner.cc:87  PComplexBreitWigner.cc:88  PComplexBreitWigner.cc:89  PComplexBreitWigner.cc:90  PComplexBreitWigner.cc:91  PComplexBreitWigner.cc:92  PComplexBreitWigner.cc:93  PComplexBreitWigner.cc:94  PComplexBreitWigner.cc:95  PComplexBreitWigner.cc:96  PComplexBreitWigner.cc:97  PComplexBreitWigner.cc:98  PComplexBreitWigner.cc:99  PComplexBreitWigner.cc:100  PComplexBreitWigner.cc:101  PComplexBreitWigner.cc:102  PComplexBreitWigner.cc:103  PComplexBreitWigner.cc:104  PComplexBreitWigner.cc:105  PComplexBreitWigner.cc:106  PComplexBreitWigner.cc:107  PComplexBreitWigner.cc:108  PComplexBreitWigner.cc:109  PComplexBreitWigner.cc:110  PComplexBreitWigner.cc:111  PComplexBreitWigner.cc:112  PComplexBreitWigner.cc:113  PComplexBreitWigner.cc:114  PComplexBreitWigner.cc:115  PComplexBreitWigner.cc:116  PComplexBreitWigner.cc:117  PComplexBreitWigner.cc:118  PComplexBreitWigner.cc:119  PComplexBreitWigner.cc:120  PComplexBreitWigner.cc:121  PComplexBreitWigner.cc:122  PComplexBreitWigner.cc:123  PComplexBreitWigner.cc:124  PComplexBreitWigner.cc:125  PComplexBreitWigner.cc:126  PComplexBreitWigner.cc:127  PComplexBreitWigner.cc:128  PComplexBreitWigner.cc:129  PComplexBreitWigner.cc:130  PComplexBreitWigner.cc:131  PComplexBreitWigner.cc:132  PComplexBreitWigner.cc:133  PComplexBreitWigner.cc:134  PComplexBreitWigner.cc:135  PComplexBreitWigner.cc:136  PComplexBreitWigner.cc:137  PComplexBreitWigner.cc:138  PComplexBreitWigner.cc:139  PComplexBreitWigner.cc:140  PComplexBreitWigner.cc:141  PComplexBreitWigner.cc:142  PComplexBreitWigner.cc:143  PComplexBreitWigner.cc:144  PComplexBreitWigner.cc:145  PComplexBreitWigner.cc:146  PComplexBreitWigner.cc:147  PComplexBreitWigner.cc:148  PComplexBreitWigner.cc:149  PComplexBreitWigner.cc:150  PComplexBreitWigner.cc:151  PComplexBreitWigner.cc:152  PComplexBreitWigner.cc:153  PComplexBreitWigner.cc:154  PComplexBreitWigner.cc:155  PComplexBreitWigner.cc:156  PComplexBreitWigner.cc:157  PComplexBreitWigner.cc:158  PComplexBreitWigner.cc:159  PComplexBreitWigner.cc:160  PComplexBreitWigner.cc:161  PComplexBreitWigner.cc:162  PComplexBreitWigner.cc:163  PComplexBreitWigner.cc:164  PComplexBreitWigner.cc:165  PComplexBreitWigner.cc:166  PComplexBreitWigner.cc:167  PComplexBreitWigner.cc:168  PComplexBreitWigner.cc:169  PComplexBreitWigner.cc:170  PComplexBreitWigner.cc:171  PComplexBreitWigner.cc:172  PComplexBreitWigner.cc:173  PComplexBreitWigner.cc:174  PComplexBreitWigner.cc:175  PComplexBreitWigner.cc:176  PComplexBreitWigner.cc:177  PComplexBreitWigner.cc:178  PComplexBreitWigner.cc:179  PComplexBreitWigner.cc:180  PComplexBreitWigner.cc:181  PComplexBreitWigner.cc:182  PComplexBreitWigner.cc:183  PComplexBreitWigner.cc:184  PComplexBreitWigner.cc:185  PComplexBreitWigner.cc:186  PComplexBreitWigner.cc:187  PComplexBreitWigner.cc:188  PComplexBreitWigner.cc:189  PComplexBreitWigner.cc:190  PComplexBreitWigner.cc:191  PComplexBreitWigner.cc:192  PComplexBreitWigner.cc:193  PComplexBreitWigner.cc:194  PComplexBreitWigner.cc:195  PComplexBreitWigner.cc:196  PComplexBreitWigner.cc:197  PComplexBreitWigner.cc:198  PComplexBreitWigner.cc:199  PComplexBreitWigner.cc:200  PComplexBreitWigner.cc:201  PComplexBreitWigner.cc:202  PComplexBreitWigner.cc:203  PComplexBreitWigner.cc:204  PComplexBreitWigner.cc:205  PComplexBreitWigner.cc:206  PComplexBreitWigner.cc:207  PComplexBreitWigner.cc:208  PComplexBreitWigner.cc:209  PComplexBreitWigner.cc:210  PComplexBreitWigner.cc:211  PComplexBreitWigner.cc:212  PComplexBreitWigner.cc:213  PComplexBreitWigner.cc:214  PComplexBreitWigner.cc:215  PComplexBreitWigner.cc:216  PComplexBreitWigner.cc:217  PComplexBreitWigner.cc:218  PComplexBreitWigner.cc:219  PComplexBreitWigner.cc:220  PComplexBreitWigner.cc:221  PComplexBreitWigner.cc:222  PComplexBreitWigner.cc:223  PComplexBreitWigner.cc:224  PComplexBreitWigner.cc:225  PComplexBreitWigner.cc:226  PComplexBreitWigner.cc:227  PComplexBreitWigner.cc:228  PComplexBreitWigner.cc:229  PComplexBreitWigner.cc:230  PComplexBreitWigner.cc:231  PComplexBreitWigner.cc:232  PComplexBreitWigner.cc:233  PComplexBreitWigner.cc:234  PComplexBreitWigner.cc:235  PComplexBreitWigner.cc:236  PComplexBreitWigner.cc:237  PComplexBreitWigner.cc:238  PComplexBreitWigner.cc:239  PComplexBreitWigner.cc:240  PComplexBreitWigner.cc:241  PComplexBreitWigner.cc:242  PComplexBreitWigner.cc:243  PComplexBreitWigner.cc:244  PComplexBreitWigner.cc:245  PComplexBreitWigner.cc:246  PComplexBreitWigner.cc:247  PComplexBreitWigner.cc:248  PComplexBreitWigner.cc:249  PComplexBreitWigner.cc:250  PComplexBreitWigner.cc:251  PComplexBreitWigner.cc:252  PComplexBreitWigner.cc:253  PComplexBreitWigner.cc:254  PComplexBreitWigner.cc:255  PComplexBreitWigner.cc:256  PComplexBreitWigner.cc:257  PComplexBreitWigner.cc:258  PComplexBreitWigner.cc:259  PComplexBreitWigner.cc:260  PComplexBreitWigner.cc:261  PComplexBreitWigner.cc:262  PComplexBreitWigner.cc:263  PComplexBreitWigner.cc:264  PComplexBreitWigner.cc:265  PComplexBreitWigner.cc:266  PComplexBreitWigner.cc:267  PComplexBreitWigner.cc:268  PComplexBreitWigner.cc:269  PComplexBreitWigner.cc:270  PComplexBreitWigner.cc:271  PComplexBreitWigner.cc:272  PComplexBreitWigner.cc:273  PComplexBreitWigner.cc:274  PComplexBreitWigner.cc:275  PComplexBreitWigner.cc:276  PComplexBreitWigner.cc:277  PComplexBreitWigner.cc:278  PComplexBreitWigner.cc:279  PComplexBreitWigner.cc:280  PComplexBreitWigner.cc:281  PComplexBreitWigner.cc:282  PComplexBreitWigner.cc:283  PComplexBreitWigner.cc:284  PComplexBreitWigner.cc:285  PComplexBreitWigner.cc:286