import inspect


def get_parameters(name, func, hyper_parameters, internal_values):
    """Classifies the parameters of a function in hyperameters,
    internals or run inputs.

    Parameters
    ----------
    name: ``str``
        Name of the function.
    func: ``callable``
        Function to extract parameters from, usually an estimator.
    hyper_parameters: ``set``
        Set containing attributes labeled as hyperparameters.
    internal_values: ``set``
        Set containing the attributes labeled as internals.

    Returns
    ----------
    shparams: ``set``
        Set containing the function parameters classified as hyperparameters.
    sinternals: ``set``
        Set containing the function parameters classified as internals.
    sinputs: ``set``
        Set containing the function parameters classified as run inputs.
    """

    signature = inspect.signature(func)

    # for paran_name, param in signature.parameters.items():
    # first determine whether it is an hyperparameter, an internal
    # or a run input.
    shparams, sinternals, sinputs = set(), set(), set()
    for param_name, param_value in signature.parameters.items():
        if param_value.default is not param_value.empty:
            raise TypeError(
                "No default value alowed in stimuli and integration. "
                f"Function '{name} -> {param_name}={param_value.default}'"
            )
        if param_name in hyper_parameters:
            shparams.add(param_name)
        elif param_name in internal_values:
            sinternals.add(param_name)
        else:
            sinputs.add(param_name)

    return shparams, sinternals, sinputs