//Renata Kopecna

#include <options.hh>

#include <iostream>
#include <fstream>
#include <sstream>
#include <assert.h>

#include <TStyle.h>
#include <TMath.h>
#include <spdlog.h>
//https://github.com/gabime/spdlog
#include <helpers.hh>

///Try to extract a number from the name (option given on command line)
int fcnc::options::get_job_id() {
  return job_id;
};

//reset the ranges of all three angles back to full_angular configuration
void fcnc::options::reset_angle_ranges(){
    ctl_min = CTK_MIN;
    ctl_max = CTL_MAX;
    ctk_min = CTK_MIN;
    ctk_max = CTK_MAX;
    phi_min = PHI_MIN;
    phi_max = PHI_MAX;

    //spdlog::debug( "Reset angles: ctl=[ {0:0.2f} - {1:0.2f}]", ctl_min ,ctl_max);
    //spdlog::debug( "Reset angles: ctk=[ {0:0.2f} - {1:0.2f}]", ctk_min ,ctk_max);
    //spdlog::debug( "Reset angles: phi=[ {0:0.2f} - {1:0.2f}]", phi_min ,phi_max);
}

bool fcnc::options::canIFold(){
    //Check the ranges of the angles, if the ranges are smaller than the full ones, do not perform folding
    if (folding == -1) return true;
    if (PHI_MIN != -1.0*TMath::Pi() || PHI_MAX != 1.0*TMath::Pi()) return false;
    if (folding > 1 && (CTL_MIN != -1.0 || CTL_MAX != 1.0)) return false;
    return true;
}

void fcnc::options::update_angle_ranges(){
  reset_angle_ranges();
  if(full_angular || folding == -1)return;
  //Check the ranges of the angles, if the ranges are smaller than the full ones, do not perform folding
  if (!canIFold()){
      spdlog::warn("Range of the angles is assymetric, cannot perform update of folded angle ranges!");
      return;
  }
  switch(folding){
    case 0:
      phi_min = 0.;
      break;
    case 1:
      phi_min = 0.;
      ctl_min = 0.;
      break;
    case 2:
      phi_min = 0.;
      ctl_min = 0.;
      break;
    case 3:
      phi_min = -MY_PI/2.;
      phi_max = +MY_PI/2.;
      ctl_min = 0.;
      break;
    case 4:
      phi_min = -MY_PI/2.;
      phi_max = +MY_PI/2.;
      ctl_min = 0.;
      ctk_max = std::min(fabs(CTK_MIN), fabs(CTK_MAX)); //Take smaller value from abs(max), abs(min) = M
      ctk_min = -ctk_max;                        //And take range (-M,M)
    break;
  }

  spdlog::debug( "Update angles: ctl=[{0:0.2f} - {1:0.2f}]", ctl_min ,ctl_max);
  spdlog::debug( "Update angles: ctk=[{0:0.2f} - {1:0.2f}]", ctk_min ,ctk_max);
  spdlog::debug( "Update angles: phi=[{0:0.2f} - {1:0.2f}]", phi_min ,phi_max);

}
///This method prints the used options.

void fcnc::options::print(){
  spdlog::info( "Options:");
  spdlog::info( "Number of threads:\t\t {0:d}", ncores);
  spdlog::info( "Use angular acceptance:          " + boolToString(use_angular_acc));
  spdlog::info( "Fit angular corr. coefficients   "+ boolToString(angularacceptance));
  spdlog::info( "Do projections:                  "+ boolToString(project));
  spdlog::info( "Write eps files:                 "+ boolToString(write_eps));
  spdlog::info( "Write C files:                   "+ boolToString(write_C));
  spdlog::info( "Load only truthmatched:          "+ boolToString(only_truthmatched));
  spdlog::info( "Use only true quantities:        "+ boolToString(use_truth));
  spdlog::info( "Shift likelihood:                "+ boolToString(shift_lh));
  spdlog::info( "Repeat on error:                 "+ boolToString(repeat_on_fail));
  spdlog::info( "Use asymmetric Minos errors:     "+ boolToString(minos_errors));
  spdlog::info( "Run Simplex before Migrad:       "+ boolToString(simplex_prerun));
  spdlog::info( "Run Hesse after Migrad:          "+ boolToString(hesse_postrun));
  spdlog::info( "Perform weighted fit:            "+ boolToString(weighted_fit));
  spdlog::info( "Verbosity:                       "+ spdlog::default_logger_raw()->level());
  spdlog::info( "Static seed:                     "+ boolToString(static_seed));
  spdlog::info( "Always static seed:              "+ boolToString(always_static_seed));
  spdlog::info( "Refit the same data set:         "+ boolToString(refitting_nominal));
}

std::vector<std::string> fcnc::options::getAllPlotTypes(){
    std::vector<std::string> ext;
    if (write_C) ext.push_back("C");
    if (write_eps) ext.push_back("eps");
    if (write_jpg) ext.push_back("jpg");
    if (write_pdf) ext.push_back("pdf");
    return ext;
}


//Get the number of Q2 bins from the lenght of ThQ2binsmin vector
unsigned int fcnc::options::get_nQ2bins(){
    return TheQ2binsmin.size();
}
//////////////////////////////
//  Set systematics options //
//////////////////////////////

void which_systematics( fcnc::options opts, int job_id){

    if(opts.systematic == 1){
      spdlog::info( "Run systematic study #1: BOOTSTRAPPING of PHSP MC");
      opts.write_eps = job_id == -1;
    }
    if(opts.systematic == 2){
      spdlog::info( "Run systematic study #2: Forced symmetric acceptance correction in cos(Theta_L)");
      opts.write_eps = false;
    }
    opts.orderincrease = 2;
    if(opts.systematic == 3){
      spdlog::info( "Run systematic study #3: Increase of Legendre order of PHSP MC parametrization");
      opts.eff_order_costhetal += opts.orderincrease;
      opts.eff_order_costhetak += opts.orderincrease;
      opts.eff_order_phi       += opts.orderincrease;
      opts.eff_order_q2        += opts.orderincrease;
    }
    if(opts.systematic == 4){
      spdlog::info( "Run systematic study #4: Vary PHSP MC reweights within their uncertainty");
      opts.write_eps = false;
    }
    if(opts.systematic == 5){
      spdlog::info( "Run systematic study #5: Vary S-wave fraction FS in q2bin within its uncertainty");
      opts.write_eps = false;
    }
    if(opts.systematic == 6){
      spdlog::info( "Run systematic study #6: Vary angles (ctk, ctl and phi) within the angular resoluation");
      opts.write_eps = false;
    }
    if(opts.systematic == 7){
      spdlog::info( "Run systematic study #7: Generate toy events with double-gaussian profile and fit with CB");
      opts.write_eps = false;
    }
    if(opts.systematic == 8){
      spdlog::info( "Run systematic study #8: Systematic study on angular background model");
      opts.write_eps = false;
    }
    if(opts.systematic == 9){
      spdlog::info( "Run systematic study #9: Investigate systematic effects due to trigger selection");
      opts.write_eps = false;
    }
    if(opts.systematic == 10){
      spdlog::info( "Run systematic study #10: Reweight the PHSP MC according to discrepancy in Kshort PT distributions for DD tracks");
      opts.write_eps = false;
    }
    if(opts.systematic == 11){
      spdlog::info( "Run systematic study #11: Remove a gaussian shaped hole in the upper mass sideband of the background to mimic the B0 veto");
      opts.write_eps = false;
    }

}

std::vector<std::string> get_observables_vec (fcnc::options opts){
    std::vector<std::string> obs;
    if(opts.fit_fl) obs.push_back("Fl");
    else            obs.push_back("S1s");

    obs.push_back("S3");

    if(opts.full_angular || opts.folding == 1) obs.push_back("S4");
    if(opts.full_angular || opts.folding == 2) obs.push_back("S5");
    if(opts.full_angular || opts.folding == 0){
      if(opts.fit_afb) obs.push_back("Afb");
      else obs.push_back("S6s");
    }
    if(opts.full_angular || opts.folding == 3) obs.push_back("S7");
    if(opts.full_angular || opts.folding == 4) obs.push_back("S8");
    if(opts.full_angular || opts.folding == 0) obs.push_back("S9");
    return obs;

}


void set_ang_year_options(fcnc::options &opts){
    //Takes care of setting the year/run options for angular corrections

    //use data from run 1 and run 2 combined
    opts.angacccorrbothruns = (opts.run == 12);
    //use 2015+2016 or 2017+2018
    opts.angacccorrpertwoyears = (opts.run == 21 || opts.run == 22);
    //If run/two years are used, turn off the per-year correction
    if (opts.angacccorrbothruns || opts.angacccorrpertwoyears) opts.angacccorrperyear = false;
    return;
}

bool is_param_folded(int param, fcnc::options *opts){
    //int param is the number of the parameter according to get_angObser_withTeX_vec()
    //if the parameter is folded, return true

    if (param==5) return !(opts->full_angular || opts->folding == 1);
    if (param==6) return !(opts->full_angular || opts->folding == 2);
    if (param==7) return !(opts->full_angular || opts->folding == 0);
    if (param==8) return !(opts->full_angular || opts->folding == 0);
    if (param==9) return !(opts->full_angular || opts->folding == 3);
    if (param==10) return !(opts->full_angular || opts->folding == 4);
    if (param==11) return !(opts->full_angular || opts->folding == 0);
    return false;


}
