-----
    Brief
    -----
    Universal function for reading .txt, .h5 and .edf (future) files generated by OpenSignals.

    -----------
    Description
    -----------
    Each acquisition made using the OpenSignals software (available at https://www.biosignalsplux.com/en/software)
    stores the acquired data in three file formats: .txt, .h5 and .edf.

    This function facilitates the opening of the 3 types of files in order to provide the tools for the user to focus
    on the data processing and signal analysis instead of how to read the formatted files.

    ----------
    Parameters
    ----------
    file : file path or url (for url 'remote' field needs to be True)
        File path.

    channels : list [[mac_address_1_channel_1 <int>, mac_address_1_channel_2 <int>...],
                    [mac_address_2_channel_1 <int>...]...]
        From which channels will the data be loaded.

    devices : list ["mac_address_1" <str>, "mac_address_2" <str>...]
        List of devices selected by the user.

    get_header : boolean
        If True the file header will be returned as one of the function outputs.

    remote : boolean, optional
        If is True, then the file argument is assumed to be a url where the file can be downloaded.

    out_dict : bool, optional
        A flag that indicates if the returned dict should contain or not "Mac-address" has a key at level 1.

    signal_sample : bool, optional
        A flag indicating if the load function is being invoked by "load_signal" (function intended to load signal
        samples stored inside a repository).
        If it is True, then the loaded file will be renamed to a general identifier name "download_file".

    **kwargs : list of variable keyword arguments.

    Returns
    -------
    out : ndarray or dict, dict (optional)
        Data read from the input file and the header dictionary when get_header is True.
        When more than one device is specified the returned data is organized in a dictionary where
        each mac address of the device defines a key.

def load(file, channels=None, devices=None, get_header=False, remote=False, out_dict=False, signal_sample=False, **kwargs):
    """
    -----
    Brief
    -----
    Universal function for reading .txt, .h5 and .edf (future) files generated by OpenSignals.

    -----------
    Description
    -----------
    Each acquisition made using the OpenSignals software (available at https://www.biosignalsplux.com/en/software)
    stores the acquired data in three file formats: .txt, .h5 and .edf.

    This function facilitates the opening of the 3 types of files in order to provide the tools for the user to focus
    on the data processing and signal analysis instead of how to read the formatted files.

    ----------
    Parameters
    ----------
    file : file path or url (for url 'remote' field needs to be True)
        File path.

    channels : list [[mac_address_1_channel_1 <int>, mac_address_1_channel_2 <int>...],
                    [mac_address_2_channel_1 <int>...]...]
        From which channels will the data be loaded.

    devices : list ["mac_address_1" <str>, "mac_address_2" <str>...]
        List of devices selected by the user.

    get_header : boolean
        If True the file header will be returned as one of the function outputs.

    remote : boolean, optional
        If is True, then the file argument is assumed to be a url where the file can be downloaded.

    out_dict : bool, optional
        A flag that indicates if the returned dict should contain or not "Mac-address" has a key at level 1.

    signal_sample : bool, optional
        A flag indicating if the load function is being invoked by "load_signal" (function intended to load signal
        samples stored inside a repository).
        If it is True, then the loaded file will be renamed to a general identifier name "download_file".

    **kwargs : list of variable keyword arguments.

    Returns
    -------
    out : ndarray or dict, dict (optional)
        Data read from the input file and the header dictionary when get_header is True.
        When more than one device is specified the returned data is organized in a dictionary where
        each mac address of the device defines a key.
    """

    # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Downloading of file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    if remote is True:
        # if not os.path.exists("tempOST"):
        #     os.makedirs("tempOST")

        # Check if it is a Google Drive link.
        if "drive.google" in file:
            response = requests.get(file)
            content_type = response.headers['content-type']
            extension = mimetypes.guess_extension(content_type)
        else:
            extension = "." + file.split(".")[-1]

        if None not in [TEMP_PATH,
                        datetime.datetime.now().strftime("%Y" + "_" + "%m" + "_" + "%d" +
                                                                 "_" + "%H_%M_%S"),
                        extension]:
            remote_file_path = (TEMP_PATH + "file_" + datetime.datetime.now().strftime("%Y" + "_" + "%m" + "_" + "%d" + "_" + "%H_%M_%S") + extension).replace("\\", "/")
            file = wget.download(file, remote_file_path)
        else:
            file = wget.download(file)


    # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Verification of file type %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    file_type = _file_type(file)

    # %%%%%%%%%%%%%%% Verification if shape of channels and devices is the same %%%%%%%%%%%%%%%%%%%
    _check_shape_and_type(devices, channels)

    # =============================================================================================
    # ================== Load data accordingly to file type (Read of Header) ======================
    # =============================================================================================

    header = read_header(file)

    # =============================================================================================
    # ========= Verification if the function inputs ("devices" and "channels") are valid ==========
    # =============================================================================================

    dev_list = list(header.keys())  # Device list.
    if devices is None:
        # When None is defined as the value of the devices input then this means that all
        # devices are relevant.
        devices = dev_list
        if channels is not None:
            channels = [channels]

    # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Devices %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    dev_list_standard = _check_dev_type(devices, dev_list)

    # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Channels %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    chn_dict = _available_channels(devices, header)
    chn_list_standard = _check_chn_type(channels, chn_dict)

    # =============================================================================================
    # =========================== Read of Data from acquisition file ==============================
    # =============================================================================================
    data = None
    if file_type in ["txt", "plain", "bat"]:
        data = _load_txt(file, dev_list_standard, chn_list_standard, header, **kwargs)
        if remote is True:
            if extension == None:
                extension = ".txt"
                remote_file_path = "download_file_name" + extension
    elif file_type in ["h5", "x-hdf", "a"]:
        data = _load_h5(file, dev_list_standard, chn_list_standard)
        if remote is True:
            if extension == None:
                extension = ".h5"
                remote_file_path = "download_file_name" + extension
    elif file_type in ["edf", "octet-stream"]:
        raise RuntimeWarning("In the present package version loading data from .edf files is not "
                             "available yet.")

    # =============================================================================================
    # ======================= Clone downloaded file to signal library =============================
    # =============================================================================================
    project_dir = "../../signal_samples"
    if remote is True and os.path.isdir(project_dir):
        devices = list(header.keys())

        # Check the number of devices.
        nbr_devices = len(devices)
        if nbr_devices > 1:
            devices_label = "multi_hub"
        else:
            devices_label = "single_hub"

        # Get the list of used sensors.
        sensor_list = []
        channels_dev_str = ""
        resolutions_str = ""
        comments_str = ""
        for mac_i, mac in enumerate(devices):
            if len(devices) > 1 and mac_i != len(devices) - 1:
                comment_sep = "\n"
                other_sep = "\t"
            else:
                comment_sep = ""
                other_sep = ""
            sensor_list.append(header[mac]["sensor"])
            channels_dev_str += "[" + mac + "] " + str(len(sensor_list[-1])) + other_sep
            resolutions_str += "[" + mac + "] " + str(header[mac]["resolution"][0]) + " bits" + other_sep
            comments_str += "[" + mac + "] " + str(header[mac]["comments"]) + comment_sep

        sensor_list = list(set(numpy.concatenate(sensor_list)))
        # Check if date and sensor_list is in a bytes format.
        date = header[mac]["date"]
        if type(date) is bytes:
            date = date.decode("ascii")

        if type(sensor_list[0]) in [bytes, numpy.bytes_]:
            sensor_list = [item.decode('ascii') for item in sensor_list]

        date = date.replace("-", "_")
        file_extension = remote_file_path.split(".")[-1]

        shutil.copy(remote_file_path, project_dir + "/" + "signal_sample_" +
                    devices_label + "_" + "_".join(sensor_list) + "_" + date + "." + file_extension)

        # Generation of a json file with relevant metadata.
        aux_chn = list(data[mac].keys())[0]
        json_dict = {"Signal Type": " | ".join(sensor_list),
                     "Acquisition Time": time.strftime("%H:%M:%S.0", time.gmtime(len(data[mac][aux_chn]) / int(header[mac]["sampling rate"]))),
                     "Sample Rate": str(header[devices[0]]["sampling rate"]) + " Hz",
                     "Number of Hubs": str(len(devices)),
                     "Number of Channels": channels_dev_str,
                     "Resolutions": resolutions_str,
                     "Observations": comments_str}
        with open(project_dir + "/" + "signal_sample_" + devices_label + "_" +
                  "_".join(sensor_list) + "_" + date + "_info.json", 'w') as outfile:
            json.dump(json_dict, outfile)

    # =============================================================================================
    # ===================================== Outputs ===============================================
    # =============================================================================================

    # Simplify the output data format if we are only working with one device.
    nbr_devices = len(list(header.keys()))
    if nbr_devices == 1 and out_dict is False:
        mac_out = list(data.keys())[0]
        data = data[mac_out]
        header = header[mac_out]

    # Return data.
    if get_header is True:
        out = data, header
    else:
        out = data

    # [Internal code for overwrite file, after downloading, if already exists]
    if os.path.exists(file):
        if remote is False and signal_sample is True:
            shutil.copy(file, "download_file_name" + "." + file.split(".")[-1])
        elif remote is True:
            shutil.move(file, "download_file_name" + extension)

    return out