#!/usr/bin/bash
#shellcheck disable=SC1090

. "$(sfpath)" || exit 3

shellfu import pretty

shellfu import saturnin

usage() {
    mkusage "$@" \
            '[options] WISH [WISH..]' \
            '[options] -c|-C' \
            '[options] -f [FILE..]' \
        -o \
            "-1, --first            Ignore all but first URL"                           \
            "-B, --choose-browser   same as -b, but select browser interactively"       \
            "-Q, --choose-query     Same as -q, but select query interactively"         \
            "-a, --always-run       Always run browser, even without URL"               \
            "-b BIN, --browser BIN  Use browser BIN instead of auto-detection (using"   \
            "                       bmo-sensible)"                                      \
            "-c, --primary-clipboard   Get wishes from primary clipboard (selection)"   \
            "-C, --clipboard        Get wishes from 'clipboard' clipboard (Ctrl-C)"     \
            "--secondary-clipboard  Get wishes from secondary clipboard"                \
            "-f [FILE..] --file [FILE..]   Get wishes from FILEs (standard input if no" \
            "                       FILE is provided or a file is '-')"                 \
            "-l N, --limit N        Give up if there's more than N URLs to open"        \
            "-q QRY, --query QRY    Treat wishes as arguments to query QRY"             \
        -- \
            "WISH can be URI, bookmark, search query followed by its arguments, or body"\
            "of text which is then searched by uripecker to find 'hidden' queries"      \
            "or or URIs.  See uripecker documentation (\`pydoc3 uripecker\`) for"        \
            "details."

}

open_uris() {
    #
    # Open uris from $Tmp/uris
    #
    local count     # count of uris in cache
    local uri       # one URI to open
    count=$(wc -l <"$Tmp/uris")
    test "$count" -gt "$UriLimit" && {
        warn "too many URIs; giving up: $count > $UriLimit"
        return 1
    }
    test "$count" -eq 0 && {
        $RunOnEmpty && $BrowserBin &
        return 0
    }
    while read -r uri;
    do
        "$BrowserBin" "$uri" &
    done < "$Tmp/uris"
}

load_source() {
    #
    # Load source $Source
    #
    case $Source in
        args)   echo "${Args[@]}" ;;
        files)  cat "${Args[@]}"  ;;
        clip_c) xclip -o -selection clipboard ;;
        clip_p) xclip -o -selection primary   ;;
        clip_s) xclip -o -selection secondary ;;
    esac \
      | sed -r 's/[^[:print:]]+/ /' \
      | grep -I .
}

force_query() {
    #
    # Pre-pend query if needed
    #
    sed -e "/./s|^|$Query |"
}

pick_browser() {
    #
    # Find out binary name of browser to use
    #
    local hint=$1
    case "$ShowBrowserMenu:$BrowserBin" in
        true:*)     pybmo sensible -l gui.browser \
                      | cut -d: -f2 \
                      | bmo dmenu -- -p "browser$hint:" ;;
        false:)     pybmo sensible -s gui.browser        ;;
        false:*)    echo "$BrowserBin"             ;;
    esac
}

pick_query() {
    #
    # Find out query to use, if any
    #
    local hint=$1
    case "$ShowQueryMenu:$Query" in
        true:*)     saturnin__conf -j -r wish.query. \
                      | bmo dmenu --split = --split-field 1 \
                            -- -p "'query$hint:'" ;;
        false:)     :              ;;
        false:*)    echo "$Query"  ;;
    esac
}

limit_urls() {
    #
    # Limit URLs if needed
    #
    case "$FirstOnly" in
        true)       head -1 ;;
        false)      cat     ;;
    esac
}

mkhint() {
    #
    # Create query prompt hint from $1
    #
    local src=$1
    local hint
    $ShowQueryMenu || $ShowBrowserMenu || return 0
    hint=$(grep -m 10 . "$src")       || return 1
    hint=$(awk 1 ORS='↵' <<<"$hint" | sed 's/↵*$//')
    if test ${#hint} -gt 16;
    then
        echo " (${hint:0:16}…)"
    else
        echo " ($hint)"
    fi
    return 0
}

try_bookmark() {
    #
    # Try if first line in $Source is a valid bookmark name
    #
    local line
    read -r line
    debug -v line
    case "$line" in
        *=*)    return 1 ;;
        *\[*)   return 1 ;;    # ] <-- work around syntax HL bug
        *\\*)   return 1 ;;
        "")     return 1 ;;
    esac
    saturnin__conf -j "wish.bookmark.$line" \
      | grep .
}

grant_wish() {
    #
    # Grant wish to user
    #
    load_source >"$Tmp/raw"                     # without query part
    Query=$(pick_query "$(mkhint "$Tmp/raw")")
    saturnin__conf -j -r wish.query. wish.ini >"$Tmp/queries.map"
    <"$Tmp/raw" force_query >"$Tmp/baked"       # with query part
    BrowserBin=$(pick_browser "$(mkhint "$Tmp/baked")")
    test -n "$BrowserBin" || { think "no browser, aborting"; return 1; }
    {
        <"$Tmp/baked" try_bookmark \
         || <"$Tmp/baked" python3 -m uripecker "$Tmp/queries.map"
    } | awk '!seen[$0]++' | limit_urls > "$Tmp/uris"
    open_uris
}

main() {
    local Args=()                   # free arguments
    local BrowserBin                # chosen browser
    local FirstOnly=false           # drop all but first URL
    local Query                     # chosen query
    local RunOnEmpty=false          # run the browser even with empty set of wishes?
    local ShowBrowserMenu=false     # display menu to choose browser?
    local ShowQueryMenu=false       # display query selection?
    local Source=args               # source for wishes
    local Tmp                       # temporary directory
    local UriLimit=50               # maximum number of URLs to open
    local es=0                      # exit status

    #shellcheck disable=SC2034
    while true; do case $1 in
        --clipboard-secondary)    Source=clip_s;        shift 1 ;;
        -a|--always-run)          RunOnEmpty=true;      shift 1 ;;
        -b|--browser)             BrowserBin="$2";      shift 2 || usage -w "missing value after: $1" ;;
        -B|--choose-browser)      ShowBrowserMenu=true; shift 1 ;;
        -Q|--choose-query)        ShowQueryMenu=true;   shift 1 ;;
        -C|--clipboard-clipboard) Source=clip_c;        shift 1 ;;
        -c|--clipboard-primary)   Source=clip_p;        shift 1 ;;
        -f|--file)                Source=files;         shift 1 ;;
        -1|--first-only)          FirstOnly=true;       shift 1 ;;
        -l|--limit)               UriLimit="$2";        shift 2 || usage -w "missing value after: $1" ;;
        -q|--query)               Query="$2";           shift 2 || usage -w "missing value after: $1" ;;
        --)                       shift; break ;;
        -)                        break ;;
        -*)                       usage -w "unknown argument: $1" ;;
        *)                        break ;;
    esac done
    Args=( "$@" )
    test "$Source:${Args[0]}" == "args:" && usage -w "no WISHes?"

    Tmp=$(mktemp -dt bmo-wish.Tmp.XXXXXXXX)
    debug -v \
        Args \
        BrowserBin \
        FirstOnly \
        Query \
        RunOnEmpty \
        ShowBrowserMenu \
        ShowQueryMenu \
        Source \
        Tmp \
        UriLimit
    grant_wish; es=$?
    rm  -r "$Tmp"
    return "$es"
}

main "$@"
