#include "../GlobalFunctions.hh"
#include "../Paths.hpp"
#include "../Utils.hpp"


struct evtID{
    ULong64_t eventNumber = 0;
    UInt_t runNumber = 0;
};

int checkRunNumbers(string year, bool Reference, bool PHSP, string TMname, bool doGammaTM){

    bool MC = false;
    string treeAddress = GetBDToutputFile(year, getRunID(year),MC,Reference,PHSP, false, false, false);
    TFile *file = TFile::Open(treeAddress.c_str());
    TTree *tree = (TTree*)file->Get(treeName(MC,true).c_str());
    coutInfo("Year " + year + "   " + TMname);
    coutDebug("Opening tree " + treeAddress);

    ULong64_t eventNumber = 0;
    UInt_t runNumber = 0;
    ULong64_t pairingNumber = 0;
    evtID eventID;

    ULong64_t eventNumber_save = 0;
    UInt_t runNumber_save = 0;
    ULong64_t pairingNumber_save = 0;
    double IsAlone  = 0;
    int TM = 0;
    int gammaTM = 0;
    double MVA = 0.;

    string aloneBranch = getAloneBranch(MC,!(TMname == ""),TMname,doGammaTM);

    coutDebug("Alone branch name: " + aloneBranch);

    tree->SetBranchStatus("*",0);
    tree->SetBranchStatus("eventNumber",1);
    tree->SetBranchStatus("runNumber",1);
    tree->SetBranchStatus("pairingNumber",1);
    tree->SetBranchStatus("MLPresponse");
    tree->SetBranchStatus(aloneBranch.c_str());
    if (MC){
        if (TMname != "") tree->SetBranchStatus(TMname.c_str(),1);
        tree->SetBranchStatus(gammaTMbranch.c_str(),1);
    }
    tree->SetBranchAddress("eventNumber",&eventNumber);
    tree->SetBranchAddress("runNumber",&runNumber);
    tree->SetBranchAddress("pairingNumber",&pairingNumber);
    tree->SetBranchAddress("MLPresponse",&MVA);
    tree->SetBranchAddress(aloneBranch.c_str(),&IsAlone);
    if (MC){
        if (TMname != "") tree->SetBranchAddress(TMname.c_str(),&TM);
        tree->SetBranchAddress(gammaTMbranch.c_str(),&gammaTM);
    }
    coutDebug("Loaded the tree.");

    TH1D *multipleEventNumber = new TH1D("evtNumber","evtNumber",4000000,0,5000000000);
    TH1D *multiplePairingNumber = new TH1D("pairNumber","pairNumber",20000,0,10e19);
    TH1D *multipleEventRunNumber = new TH1D("evtRunNumber","evtRunNumber",4000000,0,5000000000);
    int nEntries = tree->GetEntries();
    vector<ULong64_t>eventNumberTMed = {};
    vector<ULong64_t>pairingNumberTMed = {};
    vector<evtID>IDNumberTMed = {};

    coutDebug("Starting the loop.");

    for (int i = 0; i<nEntries; i++){
        tree->GetEntry(i);
        //if (MVA <0.95) continue;
        if (!(i%10000)) coutDebug("Reading event " + to_string(i));
        if (MC && TMname != ""){
            if (!isTM(TMname,TM,doGammaTM,gammaTM)) continue;
        }
        eventNumberTMed.push_back(eventNumber);
        pairingNumberTMed.push_back(pairingNumber);

        eventID.eventNumber = eventNumber;
        eventID.runNumber=runNumber;
        IDNumberTMed.push_back(eventID);
    }
    coutInfo("Total number of TMed events: " + to_string(eventNumberTMed.size()));

    //Event number multiple candidates
    for_indexed(auto firstNumber: eventNumberTMed){
        for (vector<ULong64_t>::iterator evt = eventNumberTMed.begin()+i+1; evt < eventNumberTMed.end(); evt++){
            if (eventNumberTMed.at(i)==*evt){
                multipleEventNumber->Fill(*evt);
            }
        }
    }
     coutInfo("Total number of double candidates: " + to_string(multipleEventNumber->GetEntries()));


    //Pairing number multiple candidates
    for_indexed(auto first: pairingNumberTMed){
        for (vector<ULong64_t>::iterator tmp = pairingNumberTMed.begin()+i+1; tmp < pairingNumberTMed.end(); tmp++){
            if (pairingNumberTMed.at(i)==*tmp){
                multiplePairingNumber->Fill(*tmp/100);
            }
        }
    }

    coutInfo("Total number of double candidates from pairing function: " + to_string(multiplePairingNumber->GetEntries()));

    //Event+run number multiple candidates
    for_indexed(auto first: IDNumberTMed){
        for (vector<evtID>::iterator both = IDNumberTMed.begin()+i+1; both < IDNumberTMed.end(); both++){
            if (IDNumberTMed.at(i).eventNumber==(*both).eventNumber){
                if (IDNumberTMed.at(i).runNumber==(*both).runNumber){
                    multipleEventRunNumber->Fill((*both).eventNumber);
                }
            }
        }
    }
    coutInfo("Total number of double candidates from both event and run number: " + to_string(multipleEventRunNumber->GetEntries()));

    TH1D *h_alone = new TH1D("h_alone","h_alone", 100,0.0,1.0);
    string draw = aloneBranch + " >> h_alone";
    string cond = aloneBranch + " >0 && " + aloneBranch + "<2";
    tree->Draw(draw.c_str(),cond.c_str());
    coutInfo("Total number of double candidates: " + to_string(h_alone->GetEntries()));

    string outputName = "output" + year + TMname + (doGammaTM ? "" : "_rndGamma" ) +(Reference ? "Ref" : "") + (PHSP ? "PHSP" : "") + ".root";
    TFile *output = new TFile(outputName.c_str(),"RECREATE");
    output->cd();
    multipleEventNumber->Write();
    multiplePairingNumber->Write();
    output->Close();
    return 1;
}

int checkRunNumbersAll(string year, bool Reference, bool PHSP){
    checkRunNumbers(year, Reference, PHSP, "TMedBKGCAT", false);
    checkRunNumbers(year, Reference, PHSP, "TMed", false);
    checkRunNumbers(year, Reference, PHSP, "TMed", true);
    checkRunNumbers(year, Reference, PHSP, "", false);
    return 1;
}

int checkRunNumbersAllAll(bool Reference, bool PHSP){
    for (auto yr: yearsMC(Reference,PHSP, 12)) checkRunNumbersAll(yr, Reference, PHSP);
    return 1;
}
