import volgrids as vg

# //////////////////////////////////////////////////////////////////////////////
class ParserConfig(vg.ParserIni):
    def apply_config(self,
        scope_module: dict[str, ],
        scope_dependencies: dict[str, ],
        this_module_keys: set[str],
        all_known_keys: set[str],
    ) -> None:
        """
        Applies the configuration to the provided global dictionary.
        """
        for section in self._ini_sections.keys():
            for k, value in self.iter_splitted_lines(section):
                k = k.upper()
                if k not in this_module_keys:
                    continue
                if k not in all_known_keys:
                    raise ValueError(f"Unknown configuration: {k}.")
                scope_module[k] = self._parse_str(scope_dependencies, value)


    # --------------------------------------------------------------------------
    @staticmethod
    def _parse_str(scope: dict, str_value: str):
        ### INTEGERS
        if str_value.isdigit():
            return int(str_value)

        ### FLOATS
        try: return float(str_value)
        except ValueError: pass

        ### BOOLEANS
        if str_value.lower() in ["true", "false"]:
            return str_value.lower() == "true"

        ### STRINGS
        stripped = str_value.strip('"')
        if len(stripped) != len(str_value):
            return stripped

        stripped = str_value.strip("'")
        if len(stripped) != len(str_value):
            return stripped

        ### MODULE ATTRIBUTES
        error_message = f"Invalid configuration value: {str_value}"

        parts = str_value.split('.')
        if len(parts) < 2: raise ValueError(error_message)

        key = parts.pop(0)
        node = scope.get(key, None)
        if node is None: raise ValueError(error_message)

        while parts:
            key = parts.pop(0)
            try:
                node = node.__dict__.get(key, None)
            except (AttributeError):
                raise ValueError(error_message)
            if node is None:
                raise ValueError(error_message)
        return node


# //////////////////////////////////////////////////////////////////////////////
