import copy
import torch


def get_loss(cfg_loss):
    """
    Build the loss with the proper parameters and return it.

    Parameters
    ----------
    cfg_loss : dict
        Dictionary containing the name of the loss to use and it's specific configs.

    Returns
    -------
    loss_function : function
        The loss function.
    """
    loss_args = copy.deepcopy(cfg_loss)

    # Import proper loss class
    if loss_args['name'] == 'BinaryFocalLoss':
        exec(f"from utils.loss import {loss_args['name']}")
    else:
        exec(f"from torch.nn import {loss_args['name']}")
    loss_class = eval(loss_args['name'])
    del loss_args['name']

    # Convert to torch.tensor some argument that requires it.
    for arg_name in ['pos_weight', 'weight']:
        if arg_name in loss_args:
            loss_args[arg_name] = torch.tensor(loss_args[arg_name])

    loss_function = loss_class(**loss_args)

    return loss_function