import argparse
import random

from typing import Union

import numpy as np
import torch


# https://stackoverflow.com/a/43357954/6365092
def str2bool(v: Union[bool, str]) -> bool:
    if isinstance(v, bool):
        return v
    if v.lower() in ("yes", "true", "t", "y", "1"):
        return True
    elif v.lower() in ("no", "false", "f", "n", "0"):
        return False
    else:
        raise argparse.ArgumentTypeError("Boolean value expected.")


def sci2int(v: str) -> int:
    # Scientific Notation cannot be converted directly to int,
    # so here's a workaround
    return int(float(v))


def float_or_str(v: Union[float, str]) -> Union[float, str]:
    # If it is possible, convert to float. Otherwise leave str as it is.
    try:
        float_v = float(v)
        return float_v
    except ValueError:
        return v


def set_seed(seed):
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
