require 1.6.0

# Vibe development tasks. Run `chore list` to see them.
#
# The desktop loop and the sidecar fetch live here; tasks that belong to one
# area live with it, as `<area>/<area>.chore`, and are included below. They
# are deliberately not named `chorefile`: chore resolves a run by walking up
# for a file of that name, so `handoff/chorefile` would mean `chore list` in
# handoff/ quietly showed a partial task list with $ROOT pointing there. Every
# task therefore runs against the repo root whichever directory you are in,
# which is also why an included task can write `cd handoff/wasm`.
#
# The Python scripts under scripts/ are still the programs they always were --
# these tasks call them, they do not reimplement them. CI calls the same tasks,
# so a green local run means the same commands ran.

include handoff/handoff.chore
include website/website.chore

# The server release the app ships, a server-v* tag of this repository.
server=$(read .server-version)
bin=desktop/src-tauri/binaries

# Build server/ from the tree and put it where `setup` would have put the
# release, for iterating on the engine; run `setup` first so ffmpeg is there.
task server-build target=$TRIPLE {
    exe=""
    if $1 contains windows { exe=.exe }
    cd server
    chore fetch-libs
    cargo build -p vibe-server --release
    cd $ROOT
    mkdir $bin
    copy server/target/release/vibe-server$exe $bin/vibe-server-$1$exe
    chmod 755 $bin/vibe-server-$1$exe
    echo "built vibe-server-$1 from server/"
}

# Fetch the vibe-server and ffmpeg sidecars for this machine.
task setup target=$TRIPLE {
    # $1 is the target: this machine by default, or an explicit triple when
    # CI cross-compiles. The asset names are the server release's own; the
    # triple is also what the sidecar must be called, because Tauri looks for
    # `vibe-server-<triple>` beside the binary.
    if $1 == aarch64-apple-darwin {
        asset=vibe-server-darwin-arm64-with-ffmpeg.tar.gz
    } else if $1 == x86_64-apple-darwin {
        asset=vibe-server-darwin-amd64-with-ffmpeg.tar.gz
    } else if $1 == x86_64-pc-windows-msvc {
        asset=vibe-server-windows-amd64-with-ffmpeg.zip
    } else if $1 == x86_64-unknown-linux-gnu {
        asset=vibe-server-linux-amd64
    } else if $1 == aarch64-unknown-linux-gnu {
        asset=vibe-server-linux-arm64
    } else {
        fail "the server publishes no build for $1"
    }

    # $exe is the *host's* suffix, and $1 may name another platform, so the
    # suffix has to come from the target rather than from this machine.
    exe=""
    if $1 contains windows { exe=.exe }

    mkdir $bin
    # Linux ships the server alone; every other target gets ffmpeg beside it, so
    # both have to be there before this is a no-op. Checking only the server would
    # leave a half-populated $bin in place and the Tauri build would fail much later.
    if $1 contains linux {
        if exists $bin/vibe-server-$1 {
            echo "sidecars for $1 are already in place"
            return
        }
    } else if exists $bin/vibe-server-$1$exe && exists $bin/ffmpeg-$1$exe {
        echo "sidecars for $1 are already in place"
        return
    }

    if $1 contains linux {
        # Linux ships the bare binary, with no ffmpeg alongside it. This is
        # keyed on the target, not the host, so a cross-compile picks the same
        # branch CI's Linux runners do.
        download gh://thewh1teagle/vibe/server-$server/$asset $bin/vibe-server-$1
        chmod 755 $bin/vibe-server-$1
        echo "installed vibe-server-$1"
        return
    }

    # macOS and Windows ship an archive holding the server and ffmpeg. --flatten
    # drops whatever directories the archive puts them under, so they land in
    # $bin at a name we know; the moves only rename.
    mkdir target/sidecars
    download gh://thewh1teagle/vibe/server-$server/$asset target/sidecars/$asset
    extract target/sidecars/$asset $bin --member vibe-server$exe --flatten
    extract target/sidecars/$asset $bin --member ffmpeg$exe --flatten
    move $bin/vibe-server$exe $bin/vibe-server-$1$exe
    move $bin/ffmpeg$exe $bin/ffmpeg-$1$exe
    remove target/sidecars/$asset
    # Empty $exe means a non-Windows target, so these are the paths just moved
    # into place. Testing the target rather than $OS keeps a cross-compile from
    # chmod-ing a name that was never written.
    if $exe == "" {
        chmod 755 $bin/vibe-server-$1$exe
        chmod 755 $bin/ffmpeg-$1
    }
    echo "installed vibe-server-$1 and ffmpeg-$1"
}

# Install the Linux build dependencies with apt.
task linux-deps {
    # The Tauri prerequisites plus what Vibe adds on top: alsa for audio, xdo
    # for the global shortcut, and the appindicator bindings for the tray icon.
    # `setup` deliberately does not call this -- it needs sudo, and every
    # `chore dev` should not ask for a password.
    if $OS != linux {
        fail "linux-deps is for Linux; there is nothing to install on $OS"
    }
    sudo apt-get update
    sudo apt-get install -y pkg-config build-essential libglib2.0-dev libgtk-3-dev libwebkit2gtk-4.1-dev clang cmake libssl-dev libasound2-dev libxdo-dev libayatana-appindicator3-dev
}

# Install the frontend dependencies.
task install {
    cd desktop
    pnpm install
}

# Run the app in dev mode.
task dev {
    setup
    cd desktop
    pnpm exec tauri dev
}

# Run only the desktop frontend in a browser, with Tauri mocked.
task dev-web {
    cd desktop
    pnpm dev
}

# Build the app for production.
task build {
    setup
    cd desktop
    pnpm exec tauri build
}

# Rebuild vibe.app, replace the installed one and relaunch it (macOS).
task upgrade {
    # The updater artifacts are skipped: signing them needs the CI private key.
    setup
    cd desktop
    pnpm exec tauri build --bundles app --config '{"bundle":{"createUpdaterArtifacts":false}}'
    cd $ROOT
    try osascript -e 'quit app "vibe"'
    remove /Applications/vibe.app
    copy target/release/bundle/macos/vibe.app /Applications/vibe.app
    open /Applications/vibe.app
    echo "vibe upgraded and relaunched"
}

# Run the frontend tests.
task test {
    cd desktop
    pnpm test
}

# Lint the frontend and Rust, with the flags CI uses.
task lint {
    cd desktop
    pnpm lint
    cd $ROOT
    # These match .github/workflows/lint_rust.yml exactly. The justfile's
    # versions had drifted -- no --all, no --all-targets, no -D warnings --
    # so a clean `just lint` said nothing about whether CI would pass.
    cargo fmt --manifest-path Cargo.toml --all -- --check
    cargo clippy --manifest-path Cargo.toml --all-targets -- -D warnings
}

# Format everything in place.
task format {
    pnpm format
    cargo fmt
}

# Regenerate the i18n files.
task i18n {
    cd desktop
    pnpm i18n:generate
}

# Check translation coverage against en-US.
task check-i18n {
    uv run scripts/check_i18n.py
}

# Refresh the source hash on every translated changelog entry and docs page.
task stamp-translations {
    uv run scripts/content_i18n.py stamp
}

# Type-check the desktop app and the website.
task check-types {
    pnpm check-types
}

# Run every check CI runs, in one go.
task ci {
    lint
    check-types
    check-i18n
    test
}
