#!python
# System imports
import pkg_resources
import os
import sys
from optparse import Option, OptionParser, OptionGroup, make_option
from gwcosmo.create_injections import Create_injections
import argparse

data_path = pkg_resources.resource_filename('gwcosmo', 'data/')

def str2bool(v):
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')

from gwcosmo.utilities.arguments import create_parser

parser = create_parser("--run",
                       "--detectors",
                       "--asd_path",
                       "--psd",
                       "--O4sensitivity",
                       "--priors_file",
                       "--Nsamps",
                       "--days_of_O1",
                       "--days_of_O2",
                       "--days_of_O3",
                       "--days_of_O4",
                       "--duty_factor_O4_H1",
                       "--duty_factor_O4_L1",
                       "--duty_factor_O4_V1",
                       "--duty_factor_O3_H1",
                       "--duty_factor_O3_L1",
                       "--duty_factor_O3_V1",
                       "--duty_factor_O2_H1",
                       "--duty_factor_O2_L1",
                       "--duty_factor_O2_V1",
                       "--duty_factor_O1_H1",
                       "--duty_factor_O1_L1",
                       #"--ifos_config",
                       "--frame",
                       "--snr",
                       "--fmin",
                       "--sampling_frequency",
                       "--approximant",
                       "--output_dir",
                       "--Tobs",
                       "--tmp_to_dict",
                       "--tmp_to_stdout",
                       "--combine",
                       "--output_combine",
                       "--path_combine",
                       "--cpus",
                       "--merge_tmpfile_list",
                       "--dLmax_depends_on_m1",
                       "--nsbh")

opts = parser.parse_args()


combine = str2bool(opts.combine)
nsbh = str2bool(opts.nsbh)
asd_path = str(opts.asd_path)
if opts.asd_path == 'None': asd_path = data_path
if opts.psd == 'O4':
    if (opts.O4sensitivity != 'high') and (opts.O4sensitivity != 'low'):
         opts.O4sensitivity = 'low' # the pessimistic by default

if (opts.tmp_to_stdout == None) and (opts.tmp_to_dict == None) and (combine == False) and (opts.merge_tmpfile_list == None):
    print("\nCommand line options are:\n")
    for opt, value in opts.__dict__.items():
        print(opt,value)


if combine:
    Tobs = opts.Tobs
    if opts.Tobs!=None: Tobs = float(opts.Tobs)    
    injections = Create_injections(asd_path=asd_path,combine=True)
    injections.combine(path=opts.path_combine,output=opts.output_combine,Tobs=Tobs)

elif opts.merge_tmpfile_list != None:
    injections = Create_injections(asd_path=asd_path,tmpfile_to_dict=opts.merge_tmpfile_list)
    
else:
    if opts.tmp_to_dict != None:
        injections = Create_injections(tmp_to_dict=opts.tmp_to_dict)
        sys.exit()
    if opts.tmp_to_stdout != None:
        injections = Create_injections(tmp_to_stdout=opts.tmp_to_stdout)
        sys.exit()

    output_dir = str(opts.output_dir)
    psd = opts.psd
    if opts.psd=='None' : psd = None
    priors_file = opts.priors_file
    if opts.priors_file=='None':
        priors_file = None
    else:
        print("The current version of the injection code does not treat priors from file. Exiting.")
        sys.exit()
            
        
    detectors = []
    if 'H' in opts.detectors:
        detectors.append('H1')
    if 'L' in opts.detectors:
        detectors.append('L1')
    if 'V' in opts.detectors:
        detectors.append('V1')


    # in https://arxiv.org/pdf/1304.0670.pdf
    # number of days of O1: 12 September 2015 - 19 January 2016 with duty factors 64.6% (H) and 57.4% (L), i.e. 129 days
    # number of days of O2: 30 November 2016 - 25 August 2017 with duty factors 65.3% (H) and 61.8% (L), i.e. 268 days
    # Virgo/O2 was in data taking mode during 24.5 days (2017-08-01:10:00:00 - 2017-08-25:22:00:00) with a duty cycle of 85.08%.
    # So that during O2, Virgo must be considered online with a probability of 85.08% * 24.5 / 268 = 7.77%
    # Reference for Virgo/O2: https://wiki.virgo-gw.eu/DataAnalysis/DetChar/DetCharO2Summary and https://logbook.virgo-gw.eu/virgo/?r=39301
    # for O3, number of days = 330 days (28519200/86400) values are here: https://wiki.ligo.org/Operations/O3OfficialNumbers
    
    days_of_runs = {'O1':opts.days_of_O1,'O2':opts.days_of_O2,'O3':opts.days_of_O3,'O4':opts.days_of_O4}   
    duty_factors = {'O4':{'H1':opts.duty_factor_O4_H1,'L1':opts.duty_factor_O4_L1,'V1':opts.duty_factor_O4_V1},
                    'O3':{'H1':opts.duty_factor_O3_H1,'L1':opts.duty_factor_O3_L1,'V1':opts.duty_factor_O3_V1},
                    'O2':{'H1':opts.duty_factor_O2_H1,'L1':opts.duty_factor_O2_L1,'V1':opts.duty_factor_O2_V1},
                    'O1':{'H1':opts.duty_factor_O1_H1,'L1':opts.duty_factor_O1_L1,'V1':-1}}

    print("Will use duty factors: {}".format(duty_factors))

    # dLmax_m1_params cannot be modified by the user
    # it's not possible to set it on the cmdline
    # the paramaters a0, a1, a2, a3 (in this order) are those of the empirical function obtained for SNR = 9
    # dLmax(m1) = (a0+a1 m1)exp(-(m1+a2)^2/(2*a3^2))
    dLmax_m1_params = None
    '''
    if opts.dLmax_depends_on_m1 == True:
    if ((opts.snr != 9) and ((opts.snr != 10) and (opts.snr != 11) and (opts.snr != 12)) ):
    print("The dLmax(m1) case is usable only for SNR = 9, 10, 11 or 12. Exiting.")
    sys.exit()
    else:
    dLmax_m1_params = get_dLmax_params(opts.snr)
    if opts.O4sensitivity == 'low':
    dLmax_m1_params['O4'] = dLmax_m1_params['O4low']
    else:
    dLmax_m1_params['O4'] = dLmax_m1_params['O4high']
    '''                
    # default values for Mmin, Mmax and power laws in detector frame
    # mass unit is solar mass
    # luminosity distance unit is Mpc
    # the constant limit for dLmax is used in the case            
    priors_limits = {'Mmin_det':1.,
                     'Mmax_det':1000.,
                     'power_index_m1_det':-2.,
                     'power_index_m2_det':1.,
                     'power_index_dL':2.,
                     'dLmin':0.1, # Mpc
                     'dLmax':80e3} # Mpc, case of the constant dLmax, independently of m1, dummy O4 value
#                    'dLmax':{'O1':8e3,'O2':1e4,'O3':1.3e4,'O4':2e4}} # Mpc, case of the constant dLmax, independently of m1, dummy O4 value
        
    # prepare everything in Create_injections, priors, sensitivity curves, bilby computation parameters etc.
    injections = Create_injections(detectors=detectors,
                                   psd=psd,
                                   psd_opts = opts.O4sensitivity,
                                   asd_path=asd_path,
                                   days_of_runs=days_of_runs,
                                   duty_factors=duty_factors,
                                   frame=opts.frame,
                                   nprocs=opts.cpus,
                                   approx=opts.approximant,
                                   priors=priors_file,
                                   priors_limits=priors_limits,
                                   fmin=opts.fmin,
                                   sampling_frequency=opts.sampling_frequency,
                                   dLmax_depends_on_m1=opts.dLmax_depends_on_m1,
                                   dLmax_m1_params=dLmax_m1_params,
                                   SNR_thres=opts.snr,
                                   nsbh=nsbh)

    # compute injections
    injections.do_injections(Nsamps=opts.Nsamps,
                             output_dir=opts.output_dir,
                             run=opts.run) 
    
    
    
    
    


