//Renata Kopecna

#include "parse.hh"

#include <iostream>
#include <assert.h>
#include <help.hh>
#include <constants.hh>
#include <spdlog.h>
//--------------------------------------//
//  Helpers for parsing the options     //
//--------------------------------------//

int parseOpts(int argc, char *argv[], basic_params &par, basic_actions &act, int nMCEvents){

    int opt = 0;

    //Check if there are any arguments
    if(argc > 1){
        spdlog::info("Got a total of {0:d} input options.", argc);
    }
    else{
        spdlog::error("No arguments given to the program. Use '-h' to see options. Exit...");
        return 1;
    }

    //Loop over all arguments and set par and act accordingly
    //no questionmark: value afterwards, questionamrk = bool
    while((opt = getopt(argc, argv, "a?:b:c?:d:e:f:g:h?:i:j:k?:l?:m?:o:p?:q?:r:s:t?:u:v:w?:x?:y:z:")) != -1){
        switch(opt) {
        case 'a': //action: do angular resolution
            spdlog::info("Get angular resolutions!");
            act.angRes = true;
            break;
        case 'b':
            par.bin = atoi(optarg);
            spdlog::info("Running on q2 bin ", par.bin);
            break;
        case 'c':
            spdlog::info("Get angular corrections!");
            //par.dataset = 3; //Always use MC //Not needed, as PHSP is hardcoded in the corrections obvsly
            act.angCorr = true;
            break;
        case 'd':
            par.dataset = atoi(optarg);
            if (par.dataset < 0 || par.dataset > 5){
                spdlog::error("Dataset can be only 0 - 5!");
                spdlog::info("0 for signal data");
                spdlog::info("1 for signal MC,  2 for Jpsi MC");
                spdlog::info("3 for PHSP");
                spdlog::info("4 for PHSP genLVL MC");
                spdlog::info("5 for signal genLvl MC");
                return 1;
            }
            else{
                spdlog::info("Using dataset {0:d}", par.dataset);
            }
            break;
        case 'e':
            par.nEvents = atoi(optarg);
            spdlog::info("Running on {0:d} events.", par.nEvents);
            break;
        case 'f':
            act.fitType = atoi(optarg);
            if (act.fitType < 0 || act.fitType > 6){
                spdlog::error("Fit option can be only 0 - 6!");
                return 1;
            }
            else{
                spdlog::info("Fitting with option {0:d}!", act.fitType);
            }
            break;
        case 'g':
            par.folding = atoi(optarg);
            if (par.folding < 0 || par.folding > 5){
              spdlog::error("Use only folding 0 - 4. Plus option 5 for looping over all foldings.");
              return 1;
            }
            spdlog::info("Using folding {0:d}.", par.folding);
            break;
        case 'h':
            print_help();
            print_errorCodes();
            return 0;
        case 'i':
            par.index = atoi(optarg);
            spdlog::info("Using index {0:d}.", par.index);
            break;
        case 'j':
            par.jobID = atoi(optarg);
            spdlog::info("Using job index {0:d}.", par.jobID);
            break;
        case 'k':
            spdlog::info("Convert events!");
            spdlog::info("Don't forget to specify what year/run/dataset.");
            act.convert = true;
            break;
        case 'l':
            spdlog::info("Likelyhood profiles on!");
            par.likelyhood = true;
            break;
        case 'm':
            spdlog::info("Getting pulls from MC");
            act.pullsMC = true;
            break;
        case 'o':
            spdlog::info("Feldman cousins!");
            par.FeldCous = true;
            break;
        case 'p':
            spdlog::info("Using P' instead of S!");
            par.usePprime = true;
            break;
        case 'q':
            spdlog::info("Looking into reference channel!");
            par.reference = true;
            break;
        case 'r':
            par.Run = atoi(optarg);
            if(par.Run != 0 && par.Run != 1 && par.Run != 2 && par.Run != 12 && par.Run != 21 && par.Run != 22){
                spdlog::error("Used incorrect input as Run number! Can be 1, 2, 12, 21, 22 or 0 in case of per-year running.");
                return 1;
            }
            else{
                spdlog::info("Use data of Run {0:d}", par.Run);
            }
            break;
        case 's':
            act.systematics = atoi(optarg);
            spdlog::info("Systematic study {0:d}.", act.systematics);
            break;
        case 't':
            act.pullsToys = true;
            spdlog::info("Getting pulls from toys");
            break;
        case 'u':
            par.nBins = atoi(optarg);
            spdlog::info("Number of used q2 bins: {0:d}.", par.nBins);
            if (par.nBins != 0 && par.nBins != 1 && par.nBins != 2 && par.nBins !=4 && par.nBins !=5
                     && par.nBins !=8 && par.nBins !=9){ //I hope that is all :D
                spdlog::error("Wrong number of bins! Can be either 1, 2, 4 or 5 (or 8)!");
                return 1;
            }
            break;
        case 'v':
            par.verbosity = atoi(optarg);  //Set verbosity level            
            break;
        case 'w':
            act.genToys = true; //Fit generated toys. It requires -e to be set!
            break;
        case 'x':
            act.script = true;  //Run whatever script you like
            spdlog::info("Running whatever is defined in RunningScripts");
            break;
        case 'y':
            par.year = atoi(optarg);
            spdlog::info("Running on year {0:d}.", par.year);
            par.Run = 0; //Set Run=0 so it is clear what is used
            break;
        case 'z':
            par.testInt = atoi(optarg);
            spdlog::info("testInt: {0:d}.", par.testInt);
            break;
        }
    }
    return 0;
    //parse the options

}

int checkYear(basic_params par){
    if (par.Run == -1 && par.year == -1){
        spdlog::error("I need run/years specified!");
        return 1;
    }
    else return 0;
}

int checkDataset(basic_params par){
    if (par.dataset == -1){
        spdlog::error("I need dataset specified!");
        return 1;
    }
    if (par.dataset == 2){
        par.reference = true;
    }
    return 0;
}

int checkOpts(basic_params &par, basic_actions &act){
    //TODO: enhance as you add more options to act
    if (act.angRes){ //-a
        if (checkYear(par) == 1) return 1;
    }
    if (act.angCorr){ //-c
        if (par.index != -1){ //-i, means to scan the corrections
            act.angCorrScan = true;
            act.angCorr = false;
        }
    }
    if (act.convert){
        if (checkYear(par) == 1)    return 1;
        if (checkDataset(par) == 1) return 1;
    }
    if (act.fitType != -1){
        if (checkYear(par) == 1)    return 1;
        if (checkDataset(par) == 1) return 1;
    }
    if (act.fitType == 4){ //Check if dataset is not data
        if (par.dataset == 0) return 1;
        //If MC fit, i can set the polarity, useful for checks
        if (par.index == 1) par.polarity = 1;
        if (par.index == 2) par.polarity = -1;
    }
    if (par.nBins == -1){
        spdlog::warn("Number of bins in q2 is not set! Using default settings of {0:d} bins!",NBINS_DEFAULT);
        par.nBins  = NBINS_DEFAULT;
    }    
    if (act.genToys){
        if (par.nEvents == -1){
            spdlog::warn("Number of events ot be generated is not set! Using default settings of 100 events!");
            par.nEvents = 100; //Generate a default number of toy events
        }
    }
    return 0;
}

