#!/usr/bin/sh

SYS_KBD_BACKLIGHT="/sys/class/leds/kbd_backlight/brightness"
SYS_KBD_BACKLIGHT_MAX="/sys/class/leds/kbd_backlight/max_brightness"

is_integer() {
    case "$1" in
    *[!0123456789]*) return 1 ;;
    '') return 1 ;;
    *) return 0 ;;
    esac
}

print_help() {
    echo "Usage: kbd_backlight [+|-][num][%]"
}

exit_error() {
    echo "Error: $1" >&2
    exit 1
}

get_max() {
    if [ -f "$SYS_KBD_BACKLIGHT_MAX" ]; then
        MAX_BRIGHTNESS="$(cat "$SYS_KBD_BACKLIGHT_MAX" 2>/dev/null)"
    fi
}

if [ -f "$SYS_KBD_BACKLIGHT" ]; then

    # Parse argument (part 1)
    KBD_BACKLIGHT_BRIGHTNESS="$1"
    RELATIVE=
    SIGN=
    MAXREL=
    PERCENT=
    SET_MAX=
    case "$KBD_BACKLIGHT_BRIGHTNESS" in
    '')
        cat "$SYS_KBD_BACKLIGHT"
        exit 0
        ;;
    -h | --help)
        print_help
        exit 0
        ;;
    --max)
        get_max
        if is_integer "$MAX_BRIGHTNESS"; then
            echo "$MAX_BRIGHTNESS"
            exit 0
        else
            exit_error "could not retrieve max brightness"
        fi
        ;;
    MAX)
        SET_MAX=1
        ;;
    +* | -*)
        RELATIVE=Y
        SIGN="$(echo "$KBD_BACKLIGHT_BRIGHTNESS" | head -c1)"
        KBD_BACKLIGHT_BRIGHTNESS="${KBD_BACKLIGHT_BRIGHTNESS#[+-]}"
        ;;
    esac

    # Check for root
    [ "$(id -u)" = "0" ] || exit_error "you must be root to set the brightness. Use sudo"

    # Get max brightness
    get_max
    is_integer "$MAX_BRIGHTNESS" || MAX_BRIGHTNESS=255

    if [ -z "$SET_MAX" ]; then
        # Parse argument (part 2)
        if [ "$(echo "$KBD_BACKLIGHT_BRIGHTNESS" | rev | head -c3)" = "XAM" ]; then
            MAXREL=Y
            KBD_BACKLIGHT_BRIGHTNESS="${KBD_BACKLIGHT_BRIGHTNESS%MAX}"
        fi
        if [ "$(echo "$KBD_BACKLIGHT_BRIGHTNESS" | rev | head -c1)" = "%" ]; then
            PERCENT=Y
            KBD_BACKLIGHT_BRIGHTNESS="${KBD_BACKLIGHT_BRIGHTNESS%\%}"
        fi

        # Validate argument
        if [ "$MAXREL" = "Y" ] && ! { [ "$PERCENT" = "Y" ] && [ "$RELATIVE" != "Y" ]; }; then
            exit_error "'MAX' only works alone, or with % and no sign"
        fi
        if ! is_integer "$KBD_BACKLIGHT_BRIGHTNESS"; then
            exit_error "argument $KBD_BACKLIGHT_BRIGHTNESS must be a non-negative integer"
        fi
        if
            [ "$PERCENT" != "Y" ] && [ "$KBD_BACKLIGHT_BRIGHTNESS" -gt "$MAX_BRIGHTNESS" ]
        then
            exit_error "argument $KBD_BACKLIGHT_BRIGHTNESS must be between 0 and $MAX_BRIGHTNESS"
        fi

        # Calculate desired brightness
        if [ "$PERCENT" = "Y" ] || [ "$RELATIVE" = "Y" ]; then
            if [ "$MAXREL" = "Y" ]; then
                KBB="$MAX_BRIGHTNESS"
            else
                KBB="$(cat $SYS_KBD_BACKLIGHT)"
            fi
        else
            KBB="$KBD_BACKLIGHT_BRIGHTNESS"
        fi
        if [ "$PERCENT" = "Y" ]; then
            if [ "$RELATIVE" = "Y" ]; then
                if [ "$SIGN" = "+" ]; then
                    KBBD=$((100 + KBD_BACKLIGHT_BRIGHTNESS))
                else
                    KBBD=$((100 - KBD_BACKLIGHT_BRIGHTNESS))
                fi
            else
                KBBD=$((KBD_BACKLIGHT_BRIGHTNESS))
            fi
            KBB=$((KBB * KBBD))
            KBB=$((KBB / 100))
        elif [ "$RELATIVE" = "Y" ]; then
            if [ "$SIGN" = "+" ]; then
                KBB=$((KBB + KBD_BACKLIGHT_BRIGHTNESS))
            else
                KBB=$((KBB - KBD_BACKLIGHT_BRIGHTNESS))
            fi
        fi

        # Sanitize result
        if [ "$KBB" -lt 0 ]; then
            KBB=0
        elif [ "$KBB" -gt "$MAX_BRIGHTNESS" ]; then
            KBB="$MAX_BRIGHTNESS"
        fi
    else
        KBB="$MAX_BRIGHTNESS"
    fi

    # Change brightness
    echo "$KBB" >"$SYS_KBD_BACKLIGHT" 2>/dev/null
else
    exit_error "/sys/class/leds/kbd_backlight/brightness not found"
fi
