#!/bin/bash

# This script contains utility functions related to USB devices.

# Get the list of USB devices.
# Usage: get_usb_devices
get_usb_devices() {
    set -euo pipefail
    lsusb | grep -Eo ' ID .*' | cut -d' ' -f3-
}

# Get the list of USB device names.
# Usage: get_usb_device_names
get_usb_device_names() {
    set -euo pipefail
    get_usb_devices | cut -d' ' -f2-
}

# Get the list of USB devices that match the name.
# Usage: get_usb_devices_by_name <name>
get_usb_devices_by_name() {
    set -euo pipefail
    local name=${1:?Name not set}
    get_usb_device_names | while read -r device; do
        if [ "$device" = "$name" ]; then
            echo "$device"
        fi
    done
}

# Get the list of USB devices that match the pattern.
# Usage: get_usb_devices_by_pattern <pattern>
get_usb_devices_by_pattern() {
    set -euo pipefail
    local pattern=${1:?Pattern not set}
    get_usb_device_names | grep -E "$pattern"
}

# Returns the list of USB devices that match the criteria.
# Usage: usb_devices_exist <all|any> <exact|pattern> <pattern1> [pattern2] ...
usb_devices_exist() {
    set -euo pipefail
    local required=${1:?Required not set}
    local mode=${2:?Mode not set}
    shift 2
    local devices matches=0

    if [ "$#" -eq 0 ]; then
        echo "No patterns set" 1>&2
        return 1
    fi

    if ! [[ "$required" =~ ^(all|any)$ ]]; then
        echo "Invalid 'required' argument: $required" 1>&2
        return 1
    elif ! [[ "$mode" =~ ^(exact|pattern)$ ]]; then
        echo "Invalid 'mode' argument: $mode" 1>&2
        return 1
    fi

    for pattern in "$@"; do
        if [ -z "$pattern" ]; then
            echo "Got empty pattern" 1>&2
            return 1
        fi

        if [ "$mode" = "exact" ]; then
            devices="$(get_usb_devices_by_name "$pattern")"
        elif [ "$mode" = "pattern" ]; then
            devices="$(get_usb_devices_by_pattern "$pattern")"
        fi

        if [ -n "$devices" ]; then
            matches=$((matches + 1))
            echo "$devices"
        fi
    done

    if [ "$required" = "all" ]; then
        if [ "$matches" -eq "$#" ]; then
            return 0
        else
            echo "Amount of devices does not match the amount of patterns" 1>&2
            return 1
        fi
    elif [ "$required" = "any" ]; then
        if [ "$matches" -ge "0" ]; then
            return 0
        else
            echo "Amount of devices does not match the amount of patterns" 1>&2
            return 1
        fi
    fi
}
