from typing import Optional
from typing import Tuple
import torch


def config_run_env(cuda: Optional[bool] = None,
                   device_ids: Optional[Tuple[int, ...]] = None,
                   num_workers: Optional[int] = None
                   ) -> Tuple[bool, torch.device, Tuple[int, ...], int]:
    """
    Generate standard data laoding and compute parameters.

    Parameters
    ----------
    cuda : bool or None, default None
        Indicate whether to use cuda and GPUs.
    device_ids : tuple of int or None, default None
        GPU IDs to use.
    num_workers : int or None, default None
        Number of workers to use for data loading.

    Returns
    -------
    use_cuda : bool
    device : Tuple
    _device_ids : Tuple[int]
    num_workers : int
    """
    use_cuda = cuda is not None and cuda and torch.cuda.is_available()
    if use_cuda:
        if device_ids is None or len(device_ids) == 0:
            _device_ids = tuple(range(torch.cuda.device_count()))
        else:
            _device_ids = device_ids

        if num_workers is None:
            num_workers = len(_device_ids)

        device = torch.device('cuda', _device_ids[0])
    else:
        _device_ids = tuple()
        if num_workers is None:
            num_workers = 0
        device = torch.device('cpu')
    return use_cuda, device, _device_ids, num_workers