/**
 * @file options.hh
 * @author Christoph Langenbruch, Renata Kopecna
 * @date 2009-03-18
 *
 * This file contains the options class which is used to store all the settings which are needed
 * for the fit. The likelihood, fitter, and plotter classes each
 * hold a pointer to an options object which must be supplied in their constructor.
 * On initialisation of the fitter class, the chosen options are printed
 * and should be redirected to a logfile
 *
 */

#ifndef OPTIONS_H
#define OPTIONS_H

#include <string>
#include <vector>

#include <constants.hh>



namespace fcnc {

///class that stores the options used in the analysis
class options {
public:
    ///number of cores to use
    unsigned int ncores;
    ///use angular acceptance in the likelihood
    bool use_angular_acc;
    /// fit angular acceptance correction coefficients
    bool angularacceptance;
    /// get angular acceptance corrections for every year individually
    bool angacccorrperyear;
    /// combine every 2 years (2011+12, 2015+16, 2017+18) for acceptance correction
    bool angacccorrpertwoyears;
    /// combine the dataset of both runs for the angular acceptance correction:
    bool angacccorrbothruns;
    /// only calculate chi2's from the 1D projections of cos(tl), cos(tk), phi and q2
    bool only_4_1D_chi2;
    /// scan the parametrization of angular acceptance corrections coefficients
    /// by changing the max. order of legendre polynoms
    bool scan_max_order_angacccorrection;
    ///do plots after every step in a toystudy
    bool project;
    ///write .eps files
    bool write_eps;
    ///write .C files (of plots)
    bool write_C;
    ///write .jpg files (of plots)
    bool write_jpg;
    ///write .pdf files (of plots)
    bool write_pdf;
    ///read only out truthmatched bs candidates from file
    bool only_truthmatched;
    ///use only true quantities for the fit. Not implemented yet
    bool use_truth;
    ///use numerically optimal summation of likelihoods
    bool shift_lh;
    ///repeat on fail
    bool repeat_on_fail;
    ///use minos for error calculation
    bool minos_errors;
    ///use simplex first
    bool simplex_prerun;
    ///use Markov chain Monte Carlo
    bool use_mcmc;
    ///hesse postrun
    bool hesse_postrun;
    ///use accymptotic hesse, broken at this moment!!!
    bool asymptotic;
    ///weighted fit
    bool weighted_fit;
    ///generate background with acceptance correction in the PDF
    bool use_weighted_bkg;
    ///in the case of a folded and acc corrected fit, use full angular PDF for background
    bool fit_full_angular_bkg;
    ///use event q2 when determining weight
    bool use_event_norm;
    ///static seed for toys
    bool static_seed;
    ///Always use the same seed for toy generation, useful in systematics
    bool always_static_seed;
    ///extended ml fit
    bool extended_ml;
    ///refitting of nominal values for systematic studies
    bool refitting_nominal;
    ///Options to set the mass shape
    bool crystalball;
    bool twotailedcrystalball;
    bool swave;
    bool simple_mkpi;   
    //THIS TURNS ON FITTING BOTH K*mass and B+ mass
    //AND it turns off the angle fits
    bool only_mass2DFit;
    bool use_p2;
    //order of fitted polynomials
    unsigned int eff_order_costhetal;
    unsigned int eff_order_costhetak;
    unsigned int eff_order_phi;
    unsigned int eff_order_q2;
    int orderincrease;
    //order of background, currently does nothing, might be useful in the future
    unsigned int bkg_order_costhetal;
    unsigned int bkg_order_costhetak;
    unsigned int bkg_order_phi;

    //minimum and maximum mass
    bool cutsignalwindow;
    double m_min; //signal window left edge
    double m_max; //signal window right edge
    double m_low; //considered mass spectrum left edge
    double m_high; //considered mass spectrum right edge
    double q2_min;//this is only used in weighted generation
    double q2_max;
    //Initialize using the SM values?
    bool initSM;
    ///Options for all plots
    double ctl_min;
    double ctl_max;
    double ctk_min;
    double ctk_max;
    double phi_min;
    double phi_max;
    unsigned int plots_m_bins;
    unsigned int plots_mkpi_bins;
    unsigned int plots_costhetal_bins;
    unsigned int plots_costhetak_bins;
    unsigned int plots_phi_bins;
    std::string plot_label;
    std::string plot_folder;
    std::string q2_label;
    bool plot_chi2;
    std::string name;
    double minuit_strategy;
    bool flat_bkg;
    bool full_angular; //If false, use folding
    bool always_generate_full_angular; //I have no idea what it does but it is always true everywhere
    unsigned int fitsperjob;
    int job_id;
    //Fit only mass/angles/kpi mass
    bool only_Bmass; //For whatever fucking reason, this forces mkpi probability to be 1, so unless you don't fit it, set this to false
    bool only_angles;
    bool only_mkpi;
    bool reset_start;
    //for a simultaneous fit: TRUE if all param names have individual suffix to distinguish between sets of parameters
    bool use_individual_param_names;
    bool fit_asymmetries;
    bool fit_fl;
    bool fit_afb;
    bool fit_pprimes;
    //fit m(Kpi) mass spectrum?
    bool fit_mkpi; //4D+1D fit
    bool fit_lambda;
    //use the information of the m(Kpi) dimension in the angular_prob
    bool use_mkpi;  //5D fit
    bool individual_penalties;
    double mkpi_min;
    double mkpi_max;
    bool update_efficiencies;
    bool squared_hesse;
    bool mkpi_threshold;
    bool mkpi_full_range_norm;
    //Generation
    bool generate_mkpi;
    bool generate_only_bkg;
    bool isobar;
    bool multiply_eff;
    bool cache_fis;
    bool mcweight;
    bool chisquaredstudy;
    int systematic;
    bool useMC;
    int run;
    int year;
    int verbose;
    std::string DDLL;
    bool DTF;
    bool KS;
    std::vector<double> TheQ2binsmin;
    std::vector<double> TheQ2binsmax;
    bool IsFlatQ2;
    int folding;
    bool reject_identical_muon_TRUEID;
    //File used for latex output //TODO
    std::string latexFileTag;

    ///constructor
    options(std::string argument=""):
        ncores(1),
        use_angular_acc(false),
        angularacceptance(false),
        angacccorrperyear(false),
        angacccorrpertwoyears(false),
        angacccorrbothruns(false),
        only_4_1D_chi2(false),
        scan_max_order_angacccorrection(false),
        project(false),
        write_eps(false),
        write_C(false),
        write_jpg(false),
        write_pdf(false),
        shift_lh(false),
        repeat_on_fail(false),
        minos_errors(false),
        simplex_prerun(false),
        use_mcmc(false),
        hesse_postrun(true),
        asymptotic(false),
        weighted_fit(false),
        use_weighted_bkg(false),
        fit_full_angular_bkg(true),
        use_event_norm(false),
        static_seed(false),
        always_static_seed(false),
        extended_ml(false),
        refitting_nominal(true),
        crystalball(!DOUBLE_CB),
        twotailedcrystalball(DOUBLE_CB),
        swave(false),
        simple_mkpi(false),
        only_mass2DFit(false),
        use_p2(false),
        eff_order_costhetal(ORDER_COSTHETAL),
        eff_order_costhetak(ORDER_COSTHETAK),
        eff_order_phi(ORDER_PHI),
        eff_order_q2(ORDER_Q2),
        orderincrease(0),
        bkg_order_costhetal(2), //TODO
        bkg_order_costhetak(4), //TODO
        bkg_order_phi(0),       //TODO

        cutsignalwindow(false),
        m_min(PDGMASS_B-B_MASS_TIGHT_WINDOW),
        m_max(PDGMASS_B+B_MASS_TIGHT_WINDOW),
        m_low(B_MASS_LOW),
        m_high(B_MASS_HIGH),
        q2_min(-1.0),
        q2_max(-1.0),
        initSM(false),
        ctl_min(CTL_MIN),
        ctl_max(CTL_MAX),
        ctk_min(CTK_MIN),
        ctk_max(CTK_MAX),
        phi_min(PHI_MIN),
        phi_max(PHI_MAX),
        plots_m_bins(PLOT_NBINS_MB),
        plots_mkpi_bins(PLOT_NBINS_MKSTAR),
        plots_costhetal_bins(PLOT_NBINS_ANGLES),
        plots_costhetak_bins(PLOT_NBINS_ANGLES),
        plots_phi_bins(PLOT_NBINS_ANGLES),
        plot_label("LHCb 9.1 fb^{-1}"),
        plot_folder(""),
        q2_label("1.1 < q^2 < 19.0"),
        plot_chi2(false),
        name(argument),
        minuit_strategy(2.0),
        flat_bkg(false),
        full_angular(false),
        always_generate_full_angular(true),
        fitsperjob(10),
        job_id(-1),
        only_Bmass(false),
        only_angles(false),
        only_mkpi(false),
        reset_start(true),
        use_individual_param_names(false),
        fit_asymmetries(false),
        fit_fl(false),
        fit_afb(false),
        fit_pprimes(false),
        fit_mkpi(false),
        fit_lambda(false),
        use_mkpi(false),
        individual_penalties(false),
        mkpi_min(KPI_MASS_MIN),
        mkpi_max(KPI_MASS_MAX),
        update_efficiencies(true),
        squared_hesse(true),
        mkpi_threshold(false),
        mkpi_full_range_norm(false),
        generate_mkpi(false),
        generate_only_bkg(false),
        isobar(false),
        multiply_eff(false),
        cache_fis(false),
        mcweight(false), //Not changed anywhere, only in pdf to decide what weights to use and there it is always true, no clue what it is supposed to do
        chisquaredstudy(false),
        systematic(-1),
        useMC(false),
        run(-1),
        year(-1),
        verbose(2), //Set to info
        DDLL("DD"),
        DTF(true),
        KS(true),
        TheQ2binsmin(std::vector<double>(6, 0.0)),
        TheQ2binsmax(std::vector<double>(6, 0.0)),
        IsFlatQ2(true),
        folding(-1),
        reject_identical_muon_TRUEID(false),
        latexFileTag("_basic")  //TODO
    {
    };

    //assignment operator:
    options operator=(const options o){
        //self-assignment guard
        //    if (this == &o) //TODO: requires operator==
        //      return *this;
        ncores = o.ncores;
        use_angular_acc = o.use_angular_acc;
        angularacceptance = o.angularacceptance;
        angacccorrperyear = o.angacccorrperyear;
        angacccorrpertwoyears = o.angacccorrpertwoyears;
        angacccorrbothruns = o.angacccorrbothruns;
        only_4_1D_chi2 = o.only_4_1D_chi2;
        scan_max_order_angacccorrection = o.scan_max_order_angacccorrection;
        project = o.project;
        write_eps = o.write_eps;
        write_C = o.write_C;
        write_jpg = o.write_jpg;
        write_pdf = o.write_pdf;
        only_truthmatched = o.only_truthmatched;
        use_truth = o.use_truth;
        shift_lh = o.shift_lh;
        repeat_on_fail = o.repeat_on_fail;
        minos_errors = o.minos_errors;
        simplex_prerun = o.simplex_prerun;
        use_mcmc = o.use_mcmc;
        asymptotic = o.asymptotic;
        hesse_postrun = o.hesse_postrun;
        weighted_fit = o.weighted_fit;
        use_weighted_bkg = o.use_weighted_bkg;
        fit_full_angular_bkg = o.fit_full_angular_bkg;
        use_event_norm = o.use_event_norm;
        static_seed = o.static_seed;
        always_static_seed = o.always_static_seed;
        extended_ml = o.extended_ml;
        refitting_nominal = o.refitting_nominal;
        crystalball = o.crystalball;
        twotailedcrystalball = o.twotailedcrystalball;
        swave = o.swave;
        simple_mkpi = o.simple_mkpi;
        only_mass2DFit = o.only_mass2DFit;
        use_p2 = o.use_p2;
        eff_order_costhetal = o.eff_order_costhetal;
        eff_order_costhetak = o.eff_order_costhetak;
        eff_order_phi = o.eff_order_phi;
        eff_order_q2 = o.eff_order_q2;
        bkg_order_costhetal = o.bkg_order_costhetal;
        bkg_order_costhetak = o.bkg_order_costhetak;
        bkg_order_phi = o.bkg_order_phi;
        orderincrease = o.orderincrease;
        cutsignalwindow = o.cutsignalwindow;
        m_min = o.m_min;
        m_max = o.m_max;
        m_low = o.m_low;
        m_high = o.m_high;
        q2_min = o.q2_min;
        q2_max = o.q2_max;
        initSM = o.initSM;
        ctl_min = o.ctl_min;
        ctl_max = o.ctl_max;
        ctk_min = o.ctk_min;
        ctk_max = o.ctk_max;
        phi_min = o.phi_min;
        phi_max = o.phi_max;
        plots_m_bins = o.plots_m_bins;
        plots_mkpi_bins = o.plots_mkpi_bins;
        plots_costhetal_bins = o.plots_costhetal_bins;
        plots_costhetak_bins = o.plots_costhetak_bins;
        plots_phi_bins = o.plots_phi_bins;
        plot_label = o.plot_label;
        plot_folder = o.plot_folder;
        q2_label = o.q2_label;
        plot_chi2 = o.plot_chi2;
        name = o.name;
        minuit_strategy = o.minuit_strategy;
        flat_bkg = o.flat_bkg;
        full_angular = o.full_angular;
        always_generate_full_angular = o.always_generate_full_angular;
        fitsperjob = o.fitsperjob;
        job_id = o.job_id;
        only_Bmass = o.only_Bmass;
        only_angles = o.only_angles;
        only_mkpi = o.only_mkpi;
        reset_start = o.reset_start;
        use_individual_param_names = o.use_individual_param_names;
        fit_asymmetries = o.fit_asymmetries;
        fit_fl = o.fit_fl;
        fit_afb = o.fit_afb;
        fit_pprimes = o.fit_pprimes;
        fit_mkpi = o.fit_mkpi;
        fit_lambda = o.fit_lambda;
        use_mkpi = o.use_mkpi;
        individual_penalties = o.individual_penalties;
        mkpi_min = o.mkpi_min;
        mkpi_max = o.mkpi_max;
        update_efficiencies = o.update_efficiencies;
        squared_hesse = o.squared_hesse;
        mkpi_threshold = o.mkpi_threshold;
        mkpi_full_range_norm = o.mkpi_full_range_norm;
        generate_mkpi = o.generate_mkpi;
        generate_only_bkg = o.generate_only_bkg;
        isobar = o.isobar;
        multiply_eff = o.multiply_eff;
        cache_fis = o.cache_fis;
        mcweight = o.mcweight;
        chisquaredstudy = o.chisquaredstudy;
        systematic = o.systematic;
        useMC = o.useMC;
        run = o.run;
        year = o.year;
        verbose = o.verbose;
        DDLL = o.DDLL;
        DTF = o.DTF;
        KS = o.KS;
        TheQ2binsmin = o.TheQ2binsmin;
        TheQ2binsmax = o.TheQ2binsmax;
        IsFlatQ2 = o.IsFlatQ2;
        folding = o.folding;
        reject_identical_muon_TRUEID = o.reject_identical_muon_TRUEID;
        return *this;
    }

    int  get_job_id();
    //Check if the angle ranges are not interfering with the folding
    bool canIFold();
    void reset_angle_ranges();
    void update_angle_ranges();
    unsigned int get_nQ2bins();
    //Reutrns a vector with strings of all types that are required by write_eps, write_C, write_jpg and write_pdf
    std::vector<std::string> getAllPlotTypes();
    void print();
};

}

std::vector<std::string> get_observables_vec (fcnc::options opts); //TODO: add into fcnc class
void set_ang_year_options(fcnc::options &opts);

//If true, than the parameter is folded and typically set to 0 //TODO: add into fcnc class
bool is_param_folded(int param, fcnc::options *opts);
#endif
