//Renata Kopecna
#ifndef MVACLASS_HPP
#define MVACLASS_HPP

#include "GlobalFunctions.hh"

////////////////////////////////////
///
///         MVA CONFIG-CLASS
///
/// Use the txt files to keep an easy overview of the MVA variables
///
////////////////////////////////////

using namespace std;

//define MVA configurations:
struct MVAconfiguration{

    //If SplitYears is false, the MVA training will process the the selected Run (1: 2011+2012 2: 2015+2016+2017+2018 or 12: 2011-2018)
    bool SplitYears = false;
    Int_t Run = 1;
    std::vector<Int_t> years = {2011};

    Int_t KShortDecaysInVelo = 1;

    bool SplitInQ2Range = SplitInQ2;
    bool UseLowQ2Range = true;

    bool gammaTM = false;       //T: only true gammas, F: include random gamma
    string customTMbranch = "TMed";

    //to name the output files differently
    Int_t nConfiguration = 0;

} MVAconfig;

struct MVA_def{
    string ReaderName;  //Name of the MVA reader
    string LaTeXName;   //Displayed name in the plots
    string Unit;        //Unit for the branch
    int NoBr;           //Number of used branches for the reader
    string Formula;     //formula: Reader = f(Branches)
    char DataType;      //D: Double_t, F: Float_t, I: Int_t,...
};

class MVA_variables{
private:
    int NoVariables;
    int NoBranches;
public:
    vector<MVA_def> AllVariables;
    vector <string> AllBranches;

    MVA_variables(){
        NoVariables = 0;
        AllVariables.clear();
    } //empty constructor
    MVA_variables(std::string DL); //default constructor
    ~MVA_variables();   //destuctor
    void print();
    vector <string> GetAllReaderNames();
    int NumberOfVariables(){
        return NoVariables;
    }
    int NumberOfBranches(){
        return NoBranches;
    }
    vector <string> GetAllBranches(){
        return AllBranches;
    }
};

MVA_variables::MVA_variables(std::string DL){

    std:: ifstream file;
    std:: string line = "";
    MVA_def tmp;
    std::string StrTmp;
    std::string filename = thePath+"/TMVA_variables_" + TheDecay + DL + ".txt";
    file.open(filename);    //open file with the MVA variables stored; different files for different decays!
    if (file.is_open()) cout << "[INFO]\t\tInput MVA variables are being read from file "<< filename << "." <<endl;
    else{
       cout << "[ERROR]\t\tInput MVA variables file " << filename << " failed to open." << endl;
       return;
    }
    /*
    else { //in case of using this in the CodeForTests folder
        filename = "../TMVA_variables_" + TheDecay + DL + ".txt";
        file.open(filename);    //open file with the MVA variables stored; different files for different decays!
        if (file.is_open()) cout << "[INFO]\t\tInput MVA variables are being read from file "<< filename << "." <<endl;
        else{
            cout << "[ERROR]\t\tInput MVA variables file " << filename << " failed to open." << endl;
            return;
        }
    }
    */

    //list of variables suffix which get an '_DTF' appendix
    const int pp = 9;
    std::string P[pp] = {"_PX", "_PY", "_PZ", "_PT", "_PE", "_ETA", "_M", "_MERR", "_ID"};

    getline(file, line); //skipping first line with info about the file
    while(1){ //loop over lines until you find the end of the file
        getline(file, line);
        if (line == "###") break;
        if(file.eof()) break;
        std::istringstream istr(line);  //save from file to the vector
        istr >> tmp.ReaderName;
        istr >> tmp.LaTeXName;
        istr >> tmp.Unit;
        if (tmp.Unit == "0")    tmp.Unit = "";
        istr >> tmp.DataType;
        istr >> tmp.NoBr;
        istr >> tmp.Formula;
        for (int n = 0; n < tmp.NoBr; n++){
            istr >> StrTmp;
            AllBranches.push_back(StrTmp);
        }
        //DTF modifications:
        if(UseDTF){
            for(int p = 0; p < pp; p++){ //loop over suffix //ReaderNames
                size_t pos = tmp.ReaderName.find(P[p].c_str());
                if(pos!=std::string::npos){
                    coutDebug("[DTF]\t\tReplacing ReaderName '" + tmp.ReaderName);
                }
                while(pos!=std::string::npos){
                    tmp.ReaderName.replace(pos,P[p].length(),(P[p]+"_DTF").c_str());
                    pos = tmp.ReaderName.find(P[p].c_str(), pos+1);
                    if(pos==std::string::npos)coutDebug("' with '" + tmp.ReaderName + "'.");
                }
            }
        }
        AllVariables.push_back(tmp);       //Now I assume user is not an idiot!
    };
    file.close();

    if(UseDTF){
        for(int p = 0; p < pp; p++){ //loop over suffix //BranchNames
            for (unsigned int n = 0; n < AllBranches.size(); n++){
                size_t pos = AllBranches.at(n).find(P[p].c_str());
                if(pos!=std::string::npos) coutDebug("[DTF]\t\tReplacing variable '" + AllBranches.at(n));
                while(pos!=std::string::npos){
                    AllBranches.at(n).replace(pos,P[p].length(),(P[p]+"_DTF").c_str());
                    pos = AllBranches.at(n).find(P[p].c_str(), pos+1);
                    if(pos==std::string::npos)coutDebug("' with '" + AllBranches.at(n) + "'.");
                }
            }
        }
    }

    NoVariables = AllVariables.size();
    NoBranches = AllBranches.size();
    return;
}

MVA_variables::~MVA_variables(){
    AllVariables.empty();
    NoVariables = 0;
}

void MVA_variables::print(){
    coutInfo("Using " + to_string(NoVariables) + " variables.");
    coutInfo("BranchName \t\t LaTeXName \t\t Unit \t\t DataType");
    for (vector<MVA_def>::iterator tracksIter1 = AllVariables.begin(); tracksIter1 !=AllVariables.end();++tracksIter1){
        coutInfo((*tracksIter1).ReaderName + "\t\t" + (*tracksIter1).LaTeXName + "\t\t" + (*tracksIter1).Unit + "\t\t" + (*tracksIter1).DataType);
    }
}

vector <string> MVA_variables::GetAllReaderNames(){
    vector<string> tmp;
    for (vector<MVA_def>::iterator tracksIter1 = AllVariables.begin(); tracksIter1 !=AllVariables.end();++tracksIter1){
        tmp.push_back((*tracksIter1).ReaderName);
    }
    return tmp;
}


#endif // MVACLASS_HPP
