#!/bin/sh
# script/fmt: format all files (writes): the Go code with gofmt and
# then golines -m 77, the Markdown with prettier.
set -eu

ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"

# Must match the pin in script/bootstrap.
NODE_VERSION="22.17.0"

# script/bootstrap installs node and yarn under nvm and leaves neither
# on the PATH of the shell that called it, so resolve the pinned
# toolchain here the way bootstrap's own install step does. nvm is a
# bash script, hence the subshell.
run_yarn() {
    if command -v yarn >/dev/null 2>&1; then
        exec yarn "$@"
    fi
    if [ ! -s "$HOME/.nvm/nvm.sh" ]; then
        echo "fmt: no yarn; run script/bootstrap first" >&2
        exit 1
    fi
    exec bash -c '. "$HOME/.nvm/nvm.sh" && nvm use "$1" >/dev/null &&
        shift && exec yarn "$@"' bash "$NODE_VERSION" "$@"
}

# The golines that script/bootstrap installed: go install puts it in
# GOBIN, or in GOPATH/bin when GOBIN is unset.
golines_path() {
    gobin="$(go env GOBIN)"
    golines="${gobin:-$(go env GOPATH)/bin}/golines"
    if [ ! -x "$golines" ]; then
        echo "fmt: no golines; run script/bootstrap first" >&2
        exit 1
    fi
    echo "$golines"
}

main() {
    cd "$ROOT"
    golines="$(golines_path)"
    gofmt -w cmd internal
    # One golines pass can leave a line that the next pass splits
    # further, so run it until it would change nothing. The check is
    # not the while condition, where set -e would ignore a golines
    # failure.
    passes=0
    while true; do
        unformatted="$("$golines" -m 77 -l cmd internal)"
        if [ -z "$unformatted" ]; then
            break
        fi
        passes=$((passes + 1))
        if [ "$passes" -gt 5 ]; then
            echo "fmt: golines -m 77 still changes files after 5 passes" >&2
            exit 1
        fi
        "$golines" -m 77 -w cmd internal
    done
    run_yarn run prettier --write '**/*.md' --tab-width 4 --prose-wrap always
}

main "$@"
