"""
Silique (https://www.silique.fr)
Copyright (C) 2024

distribued with GPL-2 or later license

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
"""
from .helper import get_rougail_environment

from rougail.object_model import CONVERT_OPTION
from rougail.config import RougailConfig
from tiramisu.error import ValueOptionError

class RougailUserDataEnvironment:
    def __init__(self,
                 config: 'Config',
                 *,
                 rougailconfig: RougailConfig=None,
                 user_datas=None,
                 ):
        # this is the tiramisu config object
        self.config = config
        if rougailconfig is None:
            rougailconfig = RougailConfig
            user_data = rougailconfig['step.user_data']
            if 'environment' not in user_data:
                user_data.append('environment')
                rougailconfig['step.user_data'] = user_data
        user_data = rougailconfig['step.user_data']
        if 'environment' not in user_data:
            raise Exception('environment is not set in step.user_data')
        self.rougailconfig = rougailconfig
        if user_datas:
             self.errors = user_datas['errors']
             self.warnings = user_datas['warnings']
        else:
            self.errors = []
            self.warnings = []
        # bash environment variables (key/value pairs)
        self.rougail_environment_vars = get_rougail_environment()

    def run(self):
        self.config.property.read_write()
        self.parse(self.config.unrestraint)
        self.config.property.read_only()
        # about unused bash environment variables
        if len(self.rougail_environment_vars):
            unused_env_var_str = ", ".join(self.rougail_environment_vars.keys())
            self.warnings.append("the following rougail bash environment "
                                 "variable(s) are not used : " + unused_env_var_str)

    def parse(self, config):
        for option in config:
            if option.isoptiondescription():
                self.parse(option)
            else:
                # FIXME gerer les erreurs
                # try except
                # ValueError suivant le type
                # PropertyError -> hidden ou frozen...
                # pour les tests: mettre hidden à true dans le yaml
#                try:
                self.load_environment(option)
#                except Exception as exc:
#                    print(exc)
    def load_environment(self, option):
        option_name = option.path()
        # the bash variable are in upper case
        option_name = option_name.upper()
        # if the option is not in the bash environment, do nothing
        if option_name not in self.rougail_environment_vars.keys():
            return
        # actually the rougail type **is not** the same thing as
        # the tiramisu type, which is in `option.type`
        option_type = option.information.get('type')
        ismulti = option.ismulti()
        # here we retrieve the type conversion function
        # carefull, the coercion function 'func' could be None
        # -> in this case, do nothing
        type_obj = CONVERT_OPTION.get(option_type, {}).get("func")
        option_bash_value = self.rougail_environment_vars.pop(option_name)
        if ismulti:
            # here we expect the bash option value of a multi to be coma separated:
            option_bash_value = [opt.strip() for opt in option_bash_value.split(",")] 
            if type_obj:
                option_bash_value = [type_obj(opt) for opt in option_bash_value]
        elif type_obj:
            option_bash_value = type_obj(option_bash_value)
        try:
            option.value.set(option_bash_value)
        except Exception as exc:
            print(exc)