#!/usr/bin/env nix-shell
#!nix-shell -i bash -p lix wget nix-locate man xz gzip bzip2
set -euo pipefail

N_WORKERS=4
LRU_MAX_SIZE=50

# TODO: allow to pick which nix-index to fetch and use


# https://github.com/numtide/nar-serve
#HTTP_ADDR=localhost:8383 nar-serve &
#NAR_SERVE_PID=$!
#trap "set -x; kill $NAR_SERVE_PID" EXIT SIGHUP SIGINT SIGQUIT
#let N_WORKERS+=1

nix_substituters=($(nix config show substituters))
nar-fetch() {
    local storepath="$1"
    local outpath="$2"

    # /nix/store/xxx-foobar/* -> xxx
    local storehash="$(cut -c12-43 <<<"$storepath")"

    if [[ -s "$outpath" ]]; then
        return 0

    elif [[ -e "$storepath" ]]; then
        cp -v "$storepath" "$outpath"

    elif [[ -e .direnv/nar-cache/"$storehash".nar ]]; then
        mkdir -p "$(dirname "$outpath")"
        nix nar cat .direnv/nar-cache/"$storehash.nar" "/$(cut <<<"$storepath" -d/ -f5-)" >"$outpath"
        return 0

    else
        mkdir -p .direnv/nar-cache

        local prev=
        for substituter in "${nix_substituters[@]}"; do
            [[ "$substituter" != "$prev" ]] || continue
            prev="$substituter"

            local location="$((set -x; curl -L "$substituter/$storehash.narinfo") | grep '^URL: ' | cut -d' ' -f2-)" || true
            [[ -n "$location" ]] || continue

            # lru the cache
            find .direnv/nar-cache/ -maxdepth 1 -printf "%T+ %p\n" | sort | cut -d' ' -f2- | tail "-n+$LRU_MAX_SIZE" | xargs -d$'\n' rm -v

            if [[ "$location" =~ .*\.nar\.xz$ ]]; then
                (set -x; curl -L "$substituter/$location") | xz --decompress --stdout > .direnv/nar-cache/"$storehash.nar"
            elif [[ "$location" =~ .*\.nar$ ]]; then
                (set -x; curl -L "$substituter/$location") > .direnv/nar-cache/"$storehash.nar"
            else
                return 1
            fi

            mkdir -p "$(dirname "$outpath")"
            nix nar cat .direnv/nar-cache/"$storehash.nar" "/$(cut <<<"$storepath" -d/ -f5-)" >"$outpath"
            return 0
        done

    fi
}


while read attrpath size type storepath _; do
    if ! [[ "$storepath" =~ /nix/store/.* ]]; then
        continue
    fi
    outpath="data/$attrpath/$(cut -d/ -f7- <<<"$storepath")"

    #test -s "$outpath" || (
    #    mkdir -vp "$(dirname "$outpath")"
    #    set -x
    #    wget http://localhost:8383"$storepath" -O "$outpath" || true
    #)
    nar-fetch "$storepath" "$outpath" || continue

    if [[ ! -s "$outpath" ]]; then
        continue
    fi

    (
        if [[ "$outpath" =~ .*\.gz$ ]]; then
            htmlpath="html/$attrpath/$(cut -d/ -f7- <<<"$storepath" | rev | cut -d. -f2- | rev).html"
            test -s "$htmlpath" || ( set -x;
                mkdir -p "$(dirname "$htmlpath")"; man --html=cat <(zcat "$outpath") > "$htmlpath"
            )
        elif [[ "$outpath" =~ .*\.bz2$ ]]; then
            htmlpath="html/$attrpath/$(cut -d/ -f7- <<<"$storepath" | rev | cut -d. -f2- | rev).html"
            test -s "$htmlpath" || ( set -x;
                mkdir -p "$(dirname "$htmlpath")"; man --html=cat <(bzcat "$outpath") > "$htmlpath"
            )
        elif [[ "$outpath" =~ .*\.xz$ ]]; then
            htmlpath="html/$attrpath/$(cut -d/ -f7- <<<"$storepath" | rev | cut -d. -f2- | rev).html"
            test -s "$htmlpath" || ( set -x;
                mkdir -p "$(dirname "$htmlpath")"; man --html=cat <(xzcat "$outpath") > "$htmlpath"
            )
        else
            htmlpath="html/$attrpath/$(cut -d/ -f7- <<<"$storepath").html"
            test -s "$htmlpath" || ( set -x;
                mkdir -p "$(dirname "$htmlpath")"; man --html=cat "$outpath" > "$htmlpath"
            )
        fi
    ) &

    while [[ $(jobs -p | wc -l) -ge $N_WORKERS ]]; do
        >&2 echo "Waiting..."
        wait -n < <(jobs -p) || true
    done

done < <(nix-locate --regex '^/share/man/man[0-9]*/.*' --top-level   | tr -s ' ')