from typing import List
from typing import Optional
from typing import Set


def create_exp_name(flags_and_values: List[str],
                    flag_skip_set: Optional[Set[str]] = None,
                    skip_paths: bool = False) -> str:
    """
    Creates an experiment name based on the command line arguments (besides dataset and paths).

    Example: "--dataset multinews --sinkhorn" --> "dataset=multinews_sinkhorn"

    :param flags_and_values: The command line flags and their values.
    :param flag_skip_set: A set of flags to skip.
    :param skip_paths: Whether to skip paths (i.e. any flag with a value with a "/" in it).
    :return: An experiment name created based on the command line arguments.
    """
    # Remove "-" from flags
    flag_skip_set = flag_skip_set or set()
    flag_skip_set = {flag.lstrip('-') for flag in flag_skip_set}

    # Extract flags and values, skipping where necessary
    args = {}
    current_flag = None
    for flag_or_value in flags_and_values:
        if flag_or_value.startswith('-'):
            flag = flag_or_value.lstrip('-')
            current_flag = flag if flag not in flag_skip_set else None
            if current_flag is not None:
                args[current_flag] = []
        elif current_flag is not None:
            args[current_flag].append(flag_or_value)

    # Handle paths
    if skip_paths:
        for key, values in list(args.items()):
            if any('/' in value for value in values):
                del args[key]

    # Handle boolean flags
    for key, values in args.items():
        if len(values) == 0:
            values.append('True')

    exp_name = '_'.join(f'{key}={"_".join(values)}' for key, values in args.items())

    if exp_name == '':
        exp_name = 'default'

    return exp_name