app := "restree"
version := `grep 'const version' cmd/restree/main.go | cut -d'"' -f2`
bin := "bin"
dist := "dist"
pkg := "cmd/restree"
icon := "cmd/restree/icons/icon.png"

icons:
    #!/usr/bin/env bash
    set -euo pipefail
    tmp=$(mktemp -d)
    trap 'rm -rf "$tmp"' EXIT
    cp {{icon}} packaging/linux/restree.png
    oxipng -o max -z --strip all -a packaging/linux/restree.png
    magick {{icon}} -define icon:auto-resize=256,128,64,48,32,16 packaging/windows/restree.ico
    go run github.com/tc-hib/go-winres@v0.3.3 simply --arch amd64,arm64 --manifest gui --icon packaging/windows/restree.ico --out packaging/windows/restree
    sizes=()
    for size in 16 32 128 256 512; do
        magick {{icon}} -resize ${size}x${size} "$tmp/restree-${size}.png"
        sizes+=("$tmp/restree-${size}.png")
    done
    png2icns packaging/darwin/restree.icns "${sizes[@]}"

build:
    #!/usr/bin/env bash
    set -euo pipefail
    os="$(go env GOOS)"
    cpu="$(go env GOARCH)"
    mkdir -p {{bin}}
    ldflags="-s -w"
    suffix=""
    [ "$os" != windows ] || suffix=".exe"
    output="{{bin}}/{{app}}-{{version}}-$os-$cpu$suffix"
    case "$os" in
        darwin)
            unset DEVELOPER_DIR NIX_CFLAGS_COMPILE NIX_LDFLAGS NIX_CC
            sdk=$(env -u DEVELOPER_DIR /usr/bin/xcrun --sdk macosx --show-sdk-path)
            cc=$(env -u DEVELOPER_DIR /usr/bin/xcrun --sdk macosx --find clang)
            cxx=$(env -u DEVELOPER_DIR /usr/bin/xcrun --sdk macosx --find clang++)
            CC="$cc" \
            CXX="$cxx" \
            SDKROOT="$sdk" \
            MACOSX_DEPLOYMENT_TARGET="13.0" \
            CGO_CFLAGS="-isysroot $sdk -mmacosx-version-min=13.0" \
            CGO_CXXFLAGS="-std=c++17 -isysroot $sdk -mmacosx-version-min=13.0" \
            CGO_LDFLAGS="-isysroot $sdk -mmacosx-version-min=13.0" \
            GOOS="$os" GOARCH="$cpu" \
            go build -trimpath -ldflags "$ldflags -linkmode=external -extld=$cxx -extldflags=-mmacosx-version-min=13.0" -o "$output" ./{{pkg}} ;;
        windows)
            resource="packaging/windows/restree_windows_${cpu}.syso"
            copied_resource="{{pkg}}/restree_windows_${cpu}.syso"
            trap 'rm -f "$copied_resource"' EXIT
            cp -f "$resource" "$copied_resource"
            GOOS="$os" GOARCH="$cpu" go build -trimpath -ldflags "$ldflags -H=windowsgui" -o "$output" ./{{pkg}} ;;
        *)
            GOOS="$os" GOARCH="$cpu" go build -trimpath -ldflags "$ldflags" -o "$output" ./{{pkg}} ;;
    esac

package:
    #!/usr/bin/env bash
    set -euo pipefail
    os="$(go env GOOS)"
    case "$os" in
        darwin) just _package-darwin ;;
        windows) just _package-windows ;;
        linux) just build ;;
        *) echo "Unknown target: $os. Use: darwin, linux, windows"; exit 1 ;;
    esac

_package-darwin:
    #!/usr/bin/env bash
    set -euo pipefail
    arch="$(go env GOARCH)"
    just build
    app_dir="{{dist}}/Restree.app"
    rm -rf "$app_dir"
    mkdir -p "$app_dir/Contents/MacOS" "$app_dir/Contents/Resources"
    trap 'rm -rf "$app_dir"' EXIT
    cp "{{bin}}/{{app}}-{{version}}-darwin-$arch" "$app_dir/Contents/MacOS/Restree"
    cp packaging/darwin/Info.plist "$app_dir/Contents/Info.plist"
    cp packaging/darwin/restree.icns "$app_dir/Contents/Resources/restree.icns"
    macdeployqt "$app_dir" -always-overwrite -no-strip
    while IFS= read -r file; do
        dependencies=$( { otool -L "$file" 2>/dev/null || true; } | awk '$1 ~ "^/nix/store/" { print $1 }')
        for dependency in $dependencies; do
            bundled="@executable_path/../Frameworks/${dependency##*/}"
            [ -e "$app_dir/Contents/Frameworks/${dependency##*/}" ] || {
                echo "macdeployqt did not bundle $dependency" >&2
                exit 1
            }
            install_name_tool -change "$dependency" "$bundled" "$file"
        done
        { otool -l "$file" 2>/dev/null || true; } | awk '/cmd LC_RPATH/{found=1; next} found && /path \/nix\/store\//{print $2; found=0}' | while IFS= read -r rpath; do
            install_name_tool -delete_rpath "$rpath" "$file"
        done
        references=$( { otool -l "$file" 2>/dev/null || true; } | grep '/nix/store/' || true)
        [ -z "$references" ] || {
            echo "$file still references the Nix store:" >&2
            echo "$references" >&2
            exit 1
        }
    done < <(find "$app_dir/Contents" -type f)
    codesign --force --deep --sign - "$app_dir"
    /usr/bin/ditto -c -k --sequesterRsrc --keepParent "$app_dir" "{{dist}}/{{app}}-{{version}}-darwin-$arch-app.zip"

_package-windows:
    #!/usr/bin/env bash
    set -euo pipefail
    arch="$(go env GOARCH)"
    just build
    mkdir -p {{dist}}
    makensis -DARCH="$arch" packaging/windows/installer.nsi

run:
    just build
    "{{bin}}/{{app}}-{{version}}-$(go env GOOS)-$(go env GOARCH)"

check:
    just lint
    just test

lint:
    goimports -w {{pkg}}
    go vet ./{{pkg}}
    staticcheck ./{{pkg}}

test:
    go test ./...

test-race:
    go test -race ./...

bump new:
    #!/usr/bin/env bash
    set -euo pipefail
    current="{{version}}"
    new="{{new}}"
    case "$new" in
        patch|minor|major)
            IFS=. read -r current_major current_minor current_patch <<< "$current"
            case "$new" in
                patch) new="$current_major.$current_minor.$((current_patch + 1))" ;;
                minor) new="$current_major.$((current_minor + 1)).0" ;;
                major) new="$((current_major + 1)).0.0" ;;
            esac ;;
    esac
    [[ "$new" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "Usage: just bump X.Y.Z|patch|minor|major"; exit 1; }
    perl -pi -e "s/^const version = \".*\"/const version = \"$new\"/" {{pkg}}/main.go
    perl -pi -e "s/version = \".*\"/version = \"$new\"/" flake.nix
    perl -pi -e "s/!define VERSION \".*\"/!define VERSION \"$new\"/" packaging/windows/installer.nsi
    perl -pi -e 's|(<string>)[^<]*(</string>)|${1}'"$new"'${2}| if $prev =~ /CFBundle(Version|ShortVersionString)/; $prev = $_' packaging/darwin/Info.plist
    echo "Bumped to $new"
    grep -n "$new" {{pkg}}/main.go flake.nix packaging/windows/installer.nsi packaging/darwin/Info.plist

clean:
    rm -rf {{bin}} {{dist}} result {{app}} {{app}}.exe
