from typing import List
from typing import Dict
from typing import Optional
from typing import Tuple
import copy


def _split_hyper_and_pure_parameters(
    param_dict: List[Dict], pure_parameters: Optional[List[str]]
) -> List[Tuple[Optional[Dict], Optional[Dict]]]:
    """Split a list of parameters in hyperparameters and pure parameters.

    For each dictionary in the list, this separates the pure parameters (names provided in input) from all
    hyperparameters (remaining parameters).
    If either the none of the pure parameters is present in a parameter dict or all parameters are pure parameters,
    the pure or the hyperparameters are `None`.

    Returns
    -------
    split_parameters
        List of tuples `(hyper, pure)` for each of the para dicts in the input list.

    """
    if pure_parameters is None:
        return [(c, None) for c in param_dict]
    split_param_dict = []
    for c in param_dict:
        c = copy.copy(c)  # Otherwise, we remove elements from the actual parameter list that is passed as input.
        tmp = {}
        for k in list(c.keys()):
            if k in pure_parameters:
                tmp[k] = c.pop(k)
        split_param_dict.append((c or None, tmp or None))
    return split_param_dict