import os


class Environment:
    """
    A class that represents the hyperparameters to be used by ReplayBG environment.

    ...
    Attributes
    ----------
    modality : string
        A string that specifies if the function will be used to identify
        the ReplayBG model on the given data or to replay the scenario specified by the given data.
    save_name : string
        A string used to label, thus identify, each output file and result.
    replay_bg_path: string
        The current absolute path of ReplayBG.
    save_suffix : string
        A string to be attached as suffix to the resulting output files' name.
    scenario: string, {'single-meal', 'multi-meal'}
        A string that specifies whether the given scenario refers to a single-meal scenario or a multi-meal scenario.
    bolus_source : string, {'data', or 'dss'}
        A string defining whether to use, during replay, the insulin bolus data contained in the 'data' timetable (if 'data'),
        or the boluses generated by the bolus calculator implemented via the provided 'bolusCalculatorHandler' function.
    basal_source : string, {'data', 'u2ss', or 'dss'}
        A string defining whether to use, during replay, the insulin basal data contained in the 'data' timetable (if 'data'),
        or the basal generated by the controller implemented via the provided 'basalControllerHandler' function (if 'dss'),
        or fixed to the average basal rate used during identification (if 'u2ss').
    cho_source : string, {'data', 'generated'}
        A string defining whether to use, during replay, the CHO data contained in the 'data' timetable (if 'data'),
        or the CHO generated by the meal generator implemented via the provided 'mealGeneratorHandler' function.
    seed : int
        An integer that specifies the random seed. For reproducibility.
    parallelize : boolean
            A boolean that specifies whether to parallelize the identification process.
    plot_mode : boolean
        A boolean that specifies whether to show the plot of the results or not.
    verbose : boolean
        A boolean that specifies the verbosity of ReplayBG.

    Methods
    -------
    None
    """

    def __init__(self, modality, save_name, save_folder, save_suffix='', save_workspace=False, scenario='single_meal', bolus_source='data',
                 basal_source='data', cho_source='data', seed=1,
                 parallelize=False, n_processes=None, plot_mode=True, verbose=True):
        """
        Constructs all the necessary attributes for the Environment object.

        Parameters
        ----------
        modality : string
            A string that specifies if the function will be used to identify
            the ReplayBG model on the given data or to replay the scenario specified by the given data.
        save_name : string
            A string used to label, thus identify, each output file and result.
        save_suffix : string, optional, default : ''
            A string to be attached as suffix to the resulting output files' name.
        scenario: string, {'single-meal', 'multi-meal'}, optional, default : 'single-meal'
            A string that specifies whether the given scenario refers to a single-meal scenario or a multi-meal scenario.
        bolus_source : string, {'data', or 'dss'}, optional, default : 'data'
            A string defining whether to use, during replay, the insulin bolus data contained in the 'data' timetable (if 'data'),
            or the boluses generated by the bolus calculator implemented via the provided 'bolusCalculatorHandler' function.
        basal_source : string, {'data', 'u2ss', or 'dss'}, optional, default : 'data'
            A string defining whether to use, during replay, the insulin basal data contained in the 'data' timetable (if 'data'),
            or the basal generated by the controller implemented via the provided 'basalControllerHandler' function (if 'dss'),
            or fixed to the average basal rate used during identification (if 'u2ss').
        cho_source : string, {'data', 'generated'}, optional, default : 'data'
            A string defining whether to use, during replay, the CHO data contained in the 'data' timetable (if 'data'),
            or the CHO generated by the meal generator implemented via the provided 'mealGeneratorHandler' function.
        seed : int, optional, default : 1
            An integer that specifies the random seed. For reproducibility.
        parallelize : boolean, optional, default : False
            A boolean that specifies whether to parallelize the identification process.
        plot_mode : boolean, optional, default : True
            A boolean that specifies whether to show the plot of the results or not.
        verbose : boolean, optional, default : True
            A boolean that specifies the verbosity of ReplayBG.
        """

        self.modality = modality
        self.save_name = save_name
        self.replay_bg_path = save_folder

        # Create the results subfolders if they do not exist
        if not (os.path.exists(os.path.join(self.replay_bg_path, 'results'))):
            os.mkdir(os.path.join(self.replay_bg_path, 'results'))
        if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'draws'))):
            os.mkdir(os.path.join(self.replay_bg_path, 'results', 'draws'))
        if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'logs'))):
            os.mkdir(os.path.join(self.replay_bg_path, 'results', 'logs'))
        if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'mcmc_chains'))):
            os.mkdir(os.path.join(self.replay_bg_path, 'results', 'mcmc_chains'))
        if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'model_parameters'))):
            os.mkdir(os.path.join(self.replay_bg_path, 'results', 'model_parameters'))
        if not (os.path.exists(os.path.join(self.replay_bg_path, 'results', 'workspaces'))):
            os.mkdir(os.path.join(self.replay_bg_path, 'results', 'workspaces'))

        # Set the save suffix
        if save_suffix == '':
            self.save_suffix = save_suffix
        else:
            self.save_suffix = '_' + save_suffix
        self.save_workspace = save_workspace

        # Single-meal or multi-meal scenario?
        self.scenario = scenario

        # Set input sources
        self.bolus_source = bolus_source
        self.basal_source = basal_source
        self.cho_source = cho_source

        # Set the seed
        self.seed = seed

        # Set the parallelization option
        self.parallelize = parallelize
        self.n_processes = n_processes

        # Set the verbosity
        self.plot_mode = plot_mode  # if False do not plot
        self.verbose = verbose  # if False do not display stuff
