#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-only

build() {
    # prevent conflicting variables from affecting vconsole.conf values
    # shellcheck disable=SC2034
    local KEYMAP KEYMAP_TOGGLE FONT FONT_MAP FONT_UNIMAP XKBLAYOUT XKBMODEL XKBVARIANT XKBOPTIONS

    add_systemd_unit systemd-vconsole-setup.service
    add_binary /usr/lib/systemd/systemd-vconsole-setup
    add_binary loadkeys
    add_binary setfont
    if [[ -s /etc/vconsole.conf ]]; then
        add_file /etc/vconsole.conf
    else
        warning 'sd-vconsole: "/etc/vconsole.conf" not found, will use default values'
    fi

    add_udev_rule 90-vconsole.rules

    # subshell to avoid namespace pollution
    (
        shopt -s extglob nullglob

        get_decompressor() {
            case "$1" in
                *.gz)
                    cat='zcat'
                    ;;
                *.bz2)
                    cat='bzcat'
                    ;;
                *.zst)
                    cat='zstdcat'
                    ;;
                *)
                    cat='cat'
                    ;;
            esac
        }

        add_keymap_file() {
            local f
            if [[ "$1" == /* ]]; then
                # Use the exact keymap if it is specified with an absolute path
                process_keymap_file "$1"
            else
                # Search for the keymap in /usr/share/kbd/keymaps/
                while read -r f; do
                    process_keymap_file "$f"
                done < <(LC_ALL=C.UTF-8 find /usr/share/kbd/keymaps/ -type f -regex ".*/${1}\(\.map\|\.inc\)?\(\.gz\|\.bz2|\.zst\)?")
            fi
        }

        process_keymap_file() {
            local cat cmd rest f="$1"
            get_decompressor "$f"
            while read -r cmd rest; do
                if [[ "$cmd" == 'include' ]]; then
                    eval set "$rest"
                    add_keymap_file "$1"
                fi
            done < <("$cat" "$f")
            add_file "$f"
        }

        add_font_file() {
            local cat file filename fontfile="$1"
            get_decompressor "$fontfile"
            add_file "$fontfile"
            if [[ "$("$cat" "$fontfile" | head -c 23 | tr -d '\0')" == '# combine partial fonts' ]]; then
                while read -r filename; do
                    if [[ "$filename" == /* ]]; then
                        add_font_file "$filename"
                    else
                        for file in "/usr/share/kbd/consolefonts/partialfonts/$filename"?('.gz'|'.bz2'|'.zst'); do
                            add_font_file "$file"
                        done
                    fi
                done < <("$cat" "$fontfile" | sed '/^#/d')
            fi
        }

        # shellcheck disable=SC1091
        [[ -s /etc/vconsole.conf ]] && . /etc/vconsole.conf

        [[ "$KEYMAP" != '@kernel' ]] && add_keymap_file "${KEYMAP:-us}"
        [[ -n "$KEYMAP_TOGGLE" ]] && add_keymap_file "${KEYMAP_TOGGLE}"

        if [[ -n "$FONT_MAP" ]]; then
            if [[ "$FONT_MAP" == /* && -f "$FONT_MAP" ]]; then
                add_file "$FONT_MAP"
            elif [[ -f "/usr/share/kbd/consoletrans/${FONT_MAP%.trans}" ]]; then
                add_file "/usr/share/kbd/consoletrans/${FONT_MAP%.trans}"
            elif [[ -f "/usr/share/kbd/consoletrans/${FONT_MAP%.trans}.trans" ]]; then
                add_file "/usr/share/kbd/consoletrans/${FONT_MAP%.trans}.trans"
            elif [[ -f "/usr/share/kbd/consoletrans/${FONT_MAP%.trans}_to_uni.trans" ]]; then
                add_file "/usr/share/kbd/consoletrans/${FONT_MAP%.trans}_to_uni.trans"
            else
                error "sd-vconsole: requested font map not found: '%s'" "$FONT_MAP"
                return 1
            fi
        fi

        if [[ -n "$FONT_UNIMAP" ]]; then
            if [[ "$FONT_UNIMAP" == /* && -f "$FONT_UNIMAP" ]]; then
                add_file "$FONT_UNIMAP"
            elif [[ -f "/usr/share/kbd/unimaps/${FONT_UNIMAP%.uni}.uni" ]]; then
                add_file "/usr/share/kbd/unimaps/${FONT_UNIMAP%.uni}.uni"
            else
                error "sd-vconsole: requested font unimap not found: '%s'" "$FONT_UNIMAP"
                return 1
            fi
        fi

        if [[ -n "$FONT" ]]; then
            if [[ "$FONT" == /* && -f "$FONT" ]]; then
                add_font_file "$FONT"
                return
            else
                for file in "/usr/share/kbd/consolefonts/$FONT"?('.psfu'|'.psf'|'.cp'|'.fnt')?('.gz'|'.bz2'|'.zst'); do
                    add_font_file "$file"
                    return
                done
            fi
            error "sd-vconsole: requested font not found: '%s'" "$FONT"
            return 1
        fi
    )
}

help() {
    cat <<HELPEOF
This hook adds the keymap(s) and font specified in vconsole.conf to the image and
loads them during early userspace.
HELPEOF
}

# vim: set ft=sh ts=4 sw=4 et:
