# Source code for binarycpython.utils.run_system_wrapper

    """
    Module containing the utility function run_system,
    which handles a lot of things by analysing the passed kwargs
    """

    from binarycpython.utils.functions import (
        create_arg_string,
        get_arg_keys,
        remove_file,
    )

    from binarycpython.utils.custom_logging_functions import (
        create_and_load_logging_function,
    )

    from binarycpython import _binary_c_bindings

    def run_system(**kwargs):
        """
        Function that runs a system.
        Mostly as a useful utility function that handles all the setup of argument lists etc.

        Examples:
            - run_system(M_1=10): will run a system with ZAMS mass 1 = 10
            - run_system(M_1=10, log_filename="~/example_log.txt"): Will run a system
                and write the log file too
            - run_system(M_1=10, parse_function=fancy_parsing_function)

        Tasks:
            - TODO: Expand functionality.
            - TODO: Notify user when an unknown keyword is passed.

        All the arguments known to binary_c can be passed to this function as kwargs.
        Several extra arguments can be passed through the kwargs:

        Kwargs:
            custom_logging_code: Should contain a string containing the c-code for the shared library.
                If this is provided binary_c will use that custom logging code to output its data
            log_filename: Should contain name of the binary_c system log file.
                Passing this will make sure that the filename gets written for a run
                (its default behaviour is NOT to write a log file for a system)
            parse_function (function): should contain a function that parses the output.
                The parse function should take 1 required parameter: the output of the binaryc run
                Passing this will call the parse_function by passing it the output of the binary_c call
                and returns what the parse_function returns

        Returns:
            Either returns the raw output of binary_c, or the output of a parse_function if parse_function is given
        """

        # Load available arg keywords
        available_binary_c_arg_keywords = get_arg_keys()
        special_keywords = [el for el in list(available_binary_c_arg_keywords) if el.endswith("%d")]

        other_keywords = ["custom_logging_code", "log_filename", "parse_function"]

        # Set default values
        func_memaddr = -1
        write_logfile = 0

        # Create dict to pass as arg string
        binary_c_args = {}

        # Check which binary_c arguments have been passed and put them into a dict
        for key in kwargs:
            if key in available_binary_c_arg_keywords:
                binary_c_args[key] = kwargs[key]

            elif any(
                    [
                        True
                        if (key.startswith(param[:-2]) and len(param[:-2]) < len(key))
                        else False
                        for param in special_keywords
                    ]
                ):
                binary_c_args[key] = kwargs[key]

            # Notify user when this key wont be used
            else:
                if not key in other_keywords:
                    print(
                        "The following keyword was not recognised and wont be used:\n\t{}".format(
                            key
                        )
                    )

        # Check if custom logging is required
        if "custom_logging_code" in kwargs:
            func_memaddr, shared_lib_filename = create_and_load_logging_function(
                kwargs["custom_logging_code"]
            )

        # Check if writing logfile is required:
        if "log_filename" in kwargs:
            write_logfile = 1

        # Construct arguments string and final execution string
        arg_string = create_arg_string(binary_c_args)
        binary_c_command = "binary_c {}".format(arg_string)

        # Call binary_c
        output = _binary_c_bindings.run_system(
            binary_c_command,
            custom_logging_func_memaddr=func_memaddr,
            write_logfile=write_logfile,
        )

        # Remove and unload files. .
        if "custom_logging_code" in kwargs:
            remove_file(shared_lib_filename)

        if "parse_function" in kwargs:
            return kwargs["parse_function"](output)
        return output