#include <PamLevel2.h>
//--------------------------------------
//
//
//--------------------------------------
/**
 * Default constructor 
 */
PamTrack::PamTrack(){
    trk_track  = this->TrkTrack::GetTrkTrack();
    calo_track = this->CaloTrkVar::GetCaloTrkVar();
    tof_track  = this->ToFTrkVar::GetToFTrkVar();
};
//--------------------------------------
//
//
//--------------------------------------
/**
 * Constructor 
 */
PamTrack::PamTrack(TrkTrack* t, CaloTrkVar* c, ToFTrkVar* o){ 
    trk_track  = this->TrkTrack::GetTrkTrack();
    calo_track = this->CaloTrkVar::GetCaloTrkVar();
    tof_track  = this->ToFTrkVar::GetToFTrkVar();
    if(t) *trk_track  = *t;
    if(c) *calo_track = *c;
    if(o) *tof_track  = *o;
};

//--------------------------------------
//
//
//--------------------------------------
/**
 * Constructor 
 */
PamLevel2::PamLevel2(){
    trk_obj  = this->TrkLevel2::GetTrkLevel2();
    calo_obj = this->CaloLevel2::GetCaloLevel2();
    tof_obj  = this->ToFLevel2::GetToFLevel2();
    trig_obj = this->TrigLevel2::GetTrigLevel2();
    s4_obj   = this->S4Level2::GetS4Level2();
    nd_obj   = this->NDLevel2::GetNDLevel2();
    ac_obj   = this->AcLevel2::GetAcLevel2();
};
//--------------------------------------
//
//
//--------------------------------------
/**
 * Retrieves the it-th stored track. 
 * It override TrkLevel2::GetTrack(int it). 
 * @param itrk Track number, ranging from 0 to GetNTracks().
 */

PamTrack* PamLevel2::GetStoredTrack(Int_t itrk){
    
    // retrieve itrk-th tracker stored track 
    TrkTrack   *t = 0;
    CaloTrkVar *c = 0;
    ToFTrkVar  *o = 0;

    if( itrk >=0 && itrk < TrkLevel2::ntrk() ){ 
	t = TrkLevel2::GetStoredTrack(itrk);    
	c = CaloLevel2::GetCaloTrkVar(t->GetSeqNo()); 
	o = ToFLevel2::GetToFTrkVar(t->GetSeqNo()); 
    };
    //  retrieve related ToF-track
    
    // hence create a "PamTrack" object
    PamTrack *track = 0;
    if(t && c && o)track = new PamTrack(t,c,o);
    return track;
    
}
//--------------------------------------
//
//
//--------------------------------------
/**
 * Sort physical (tracker) tracks and stores them in a TObjectArray (of TrkTrack objects).
 * The total number of physical tracks is given by GetNTracks() and the it-th physical track can be retrieved by means of the method GetTrack(int it).
 * This method overrides TrkLevel2::GetTracks(), where sorting is done by decreasing number of fit points and increasing chi^2.
 * PamLevel2::GetTracks() keeps the same track order given by TrkLevel2::GetTracks(), but checks image selection by using calorimeter and ToF tracking information.
 */
TClonesArray *PamLevel2::GetTracks(){

    // define new array for sorted tracker tracks
    TClonesArray *aa = new TClonesArray("TrkTrack");
    TClonesArray &sorted = *aa;

    // loop over the tracks sorted by the tracker
    for(Int_t i=0; i < TrkLevel2::GetNTracks(); i++){

	TrkTrack *ts=0;

	// get tracker tracks
	TrkTrack   *tp = TrkLevel2::GetTrack(i);                    //tracker
	CaloTrkVar *cp = CaloLevel2::GetCaloTrkVar(tp->GetSeqNo()); //calorimeter
	ToFTrkVar  *op = ToFLevel2::GetToFTrkVar(tp->GetSeqNo());   //tof

	// if track has an image, check image selection
	if(tp->HasImage()){
	    TrkTrack   *ti = TrkLevel2::GetTrackImage(i);              //tracker (image)
	    CaloTrkVar *ci = CaloLevel2::GetCaloTrkVar(ti->GetSeqNo());//calorimeter (image)
	    ToFTrkVar  *oi = ToFLevel2::GetToFTrkVar(ti->GetSeqNo());  //tof (image)

	    //assign starting scores
	    Int_t tp_score = 1;
	    Int_t ti_score = 0;
	    // ------------------------
	    // calorimeter check
	    // ------------------------
	    if(
		      npcfit[1] > 3   &&  //no. of fit planes on Y view
//		varcfit[1] < 50.&&  //fit variance on Y view
		      true){

		Float_t resy_p = cp->tbar[0][1] - cbar[0][1];if(resy_p < 0)resy_p= - resy_p;
		Float_t resy_i = ci->tbar[0][1] - cbar[0][1];if(resy_i < 0)resy_i= - resy_i;

		if(resy_p <= resy_i) tp_score++;
		else                 ti_score++;
		      };
	    // ------------------------
	    // TOF check
	    // ------------------------	    

	    // ------------------------
	    // the winner is....
	    // ------------------------	    
		      if(tp_score > ti_score) ts = tp;//the track sorted by the tracker!!
		      else                    ts = ti;//its image!!

	}else{
	    ts = tp;
	};
	
	new(sorted[i]) TrkTrack(*ts); //save the track in the sorted array
    };

    return aa;
};
//--------------------------------------
//
//
//--------------------------------------
/**
 * Retrieves the it-th Pamela "physical" track. 
 * It override TrkLevel2::GetTrack(int it). 
 * @param it Track number, ranging from 0 to GetNTracks().
 */
PamTrack *PamLevel2::GetTrack(int it){

    TClonesArray *aa = this->GetTracks();
    TClonesArray &sorted = *aa;

    TrkTrack   *t = 0;
    CaloTrkVar *c = 0;
    ToFTrkVar  *o = 0;

    if( it >=0 && it < TrkLevel2::GetNTracks() ){
	t = (TrkTrack*)sorted[it];
	c = CaloLevel2::GetCaloTrkVar(t->GetSeqNo());
	o = ToFLevel2::GetToFTrkVar(t->GetSeqNo());
    };
    
    // hence create a "PamTrack" object
    PamTrack *track = 0;
    if(t && c && o)track = new PamTrack(t,c,o);
    return track;

};
//--------------------------------------
//
//
//--------------------------------------
/**
 * Retrieves (if present) the image of the it-th Pamela "physical" track, sorted by the method PamLevel2::GetTracks(). 
 * @param it Track number, ranging from 0 to GetNTracks().
 */
PamTrack *PamLevel2::GetTrackImage(int it){

    TClonesArray *aa = this->GetTracks();
    TClonesArray &sorted = *aa;

    TrkTrack   *t = 0;
    CaloTrkVar *c = 0;
    ToFTrkVar  *o = 0;

    if( it >=0 && it < TrkLevel2::GetNTracks() ){
	TrkTrack *temp = (TrkTrack*)sorted[it];
	if( temp->HasImage() ){
	    t = TrkLevel2::GetStoredTrack(temp->GetImageSeqNo());
	    c = CaloLevel2::GetCaloTrkVar(temp->GetImageSeqNo());
	    o = ToFLevel2::GetToFTrkVar(temp->GetImageSeqNo());
	};
    };
    
    // hence create a "PamTrack" object
    PamTrack *image = 0;
    if(t && c && o)image = new PamTrack(t,c,o);
    return image;
    
}

//--------------------------------------
//
//
//--------------------------------------
/**
 * Get the Pamela detector trees and make them friends.
 */
TTree *PamLevel2::LoadPamTrees(TFile *f){
    
    TTree *Tout =0;
    
    // Tracker
    TTree *T = (TTree*)f->Get("Tracker");
    if(T) {
        T->SetBranchAddress("TrkLevel2", GetPointerToTrk());
        cout << "Tracker      : set branch address TrkLevel2"<<endl;
        if(!Tout)Tout=T;
    }else{
        cout << "Tracker      : missing tree"<<endl;
    };
    // Calorimeter
    TTree *C = (TTree*)f->Get("Calorimeter");
    if(C) {
        C->SetBranchAddress("CaloLevel2", GetPointerToCalo());
        cout << "Calorimeter  : set branch address CaloLevel2"<<endl;
        if(!Tout)Tout=C;
        else Tout->AddFriend(C);
    }else{
        cout << "Calorimeter  : missing tree"<<endl;
    };
    // ToF    
    TTree *O = (TTree*)f->Get("ToF");
    if(O) {
        O->SetBranchAddress("ToFLevel2", GetPointerToToF());
        cout << "ToF          : set branch address ToFLevel2"<<endl;
        if(!Tout)Tout=O;
        else Tout->AddFriend(O);
    }else{
        cout << "ToF         : missing tree"<<endl;
    };
    // Trigger
    TTree *R = (TTree*)f->Get("Trigger");
    if(R) {
        R->SetBranchAddress("TrigLevel2", GetPointerToTrig());
        cout << "Trigger      : set branch address TrigLevel2"<<endl;
        if(!Tout)Tout=O;
        else Tout->AddFriend(R);
    }else{
        cout << "Trigger      : missing tree"<<endl;
    };
    // S4
    TTree *S = (TTree*)f->Get("S4");
    if(S) {
        S->SetBranchAddress("S4Level2", GetPointerToS4());
        cout << "S4           : set branch address S4Level2"<<endl;
        if(!Tout)Tout=O;
        else Tout->AddFriend(S);
    }else{
        cout << "S4           : missing tree"<<endl;
    };
    // Neutron Detector
    TTree *N = (TTree*)f->Get("NeutronD");
    if(N) {
        N->SetBranchAddress("NDLevel2", GetPointerToND());
        cout << "NeutronD     : set branch address NDLevel2"<<endl;
        if(!Tout)Tout=O;
        else Tout->AddFriend(N);
    }else{
        cout << "NeutronD     : missing tree"<<endl;
    };
    // Anticounters
    TTree *A = (TTree*)f->Get("Anticounter");
    if(A) {
        A->SetBranchAddress("AcLevel2", GetPointerToAc());
        cout << "Anticounter  : set branch address AcLevel2"<<endl;
        if(!Tout)Tout=O;
        else Tout->AddFriend(A);
    }else{
        cout << "Anticounter  : missing tree"<<endl;
    };
    
    return Tout;
    
}
