#!/usr/bin/env bash
#===============================================================================
#
#             FILE: starship.sh
#            USAGE: bash starship.sh
#
#      DESCRIPTION: installs the starship prompt and deploys my configuration
#                   (~/.config/starship.toml, gruvbox_dark preset), then wires
#                   'starship init' into your shell rc (bash and/or zsh).
#                   macOS via homebrew; Debian-like Linux via the official
#                   installer script (starship is not reliably packaged in apt).
#
#     REQUIREMENTS: curl, tar, bash; macOS+homebrew  OR  Linux (any distro)
#
#       OS SUPPORT: macOS (focus) and Linux
#
#           AUTHOR: Guto Carvalho, guto@bolha.io
#             SITE: https://gutocarvalho.net
#         MASTODON: @gutocarvalho@bolha.us
#         PIXELFED: @gutocarvalho@bolha.photos
#      WRITEFREELY: @gutocarvalho@bolha.blog
#       MATTERMOST: @gutocarvalho:mattermost.bolha.chat
#
#     ORGANIZATION: gutocarvalho.net, gcn.sh, bolha.io
#
#          CREATED: 2026-08-14
#          UPDATED: 2026-08-14
#             REPO: https://gitlab.gutocarvalho.net/open/install
#
#     CONTRIBUTORS: name, email, mastodon
#
#     The code is simple on purpose: we want it to be friendly for people
#     that are starting with shell language and programming logic.
#
#     Run it as your normal user (NOT root). On Linux it may use sudo to place
#     the binary in /usr/local/bin.
#
#===============================================================================

set -o nounset                              # treat unset variables as an error

## 1. CONSTANTS/VARIABLES ######################################################

# where to fetch the starship config from (the 'starship/' dir of this repo).
# Set STARSHIP_SRC to a local directory (with starship.toml) to deploy from disk
# instead of downloading the archive.
STARSHIP_ARCHIVE="${STARSHIP_ARCHIVE:-https://gitlab.gutocarvalho.net/open/install/-/archive/main/install-main.tar.gz}"
STARSHIP_SRC="${STARSHIP_SRC:-}"

MARKER="# starship prompt (added by install/starship.sh)"

# Nerd Font for the prompt glyphs. starship draws Nerd Font icons, so the
# TERMINAL must render with a Nerd Font or they show as boxes. We ship
# VictorMono Nerd Font (override NERD_FONT_URL for another one).
NERD_FONT_URL="${NERD_FONT_URL:-https://github.com/ryanoasis/nerd-fonts/releases/latest/download/VictorMono.zip}"

## 2. HELPERS #################################################################

### abort: print an error message and stop the script
function abort() {
  echo -e "\nError: $1" >&2
  echo -e "Tip: run 'bash -x starship.sh' to see exactly what failed.\n" >&2
  exit 1
}

### warn: print a non-fatal warning and keep going
function warn() {
  echo -e "Warning: $1" >&2
}

### check_not_root: run as the normal user (we use sudo only when needed)
function check_not_root() {
  if [ "$(id -u)" = "0" ]; then
    abort "do NOT run this as root. Run it as your normal user."
  fi
}

### need_cmd: make sure a required command exists
function need_cmd() {
  if ! command -v "$1" >/dev/null 2>&1; then
    abort "'$1' is required but was not found. Please install it first."
  fi
}

## 3. INSTALL FUNCTIONS #######################################################

### 3.1 install starship for the current OS
function install_starship() {
  if command -v starship >/dev/null 2>&1; then
    echo "starship already installed: $(starship --version | head -n1) — skipping install, will still deploy config."
    return
  fi
  echo -e "\n>>> Installing starship...\n"
  case "$(uname -s)" in
    Darwin)
      need_cmd brew
      brew install starship || abort "could not install starship with brew."
      ;;
    Linux)
      # official installer -> /usr/local/bin (it uses sudo if the dir needs it)
      curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b /usr/local/bin \
        || abort "the official starship installer failed."
      ;;
    *)
      abort "unsupported OS: $(uname -s)."
      ;;
  esac
  need_cmd starship
  echo "starship installed: $(starship --version | head -n1)"
}

### 3.1b install a Nerd Font so the prompt glyphs render (per-user, no admin)
function install_nerd_font() {
  # Runs even when starship was already installed (install_starship returns
  # early in that case). Direct download instead of the brew font cask — the
  # cask is a no-op for a second user on a multi-user Mac. You still have to
  # select the font in your terminal's settings afterwards.
  local dest os
  os="$(uname -s)"
  case "$os" in
    Darwin) dest="$HOME/Library/Fonts" ;;
    Linux)  dest="$HOME/.local/share/fonts" ;;
    *) return ;;
  esac
  if ls "$dest"/VictorMonoNerdFont*.ttf >/dev/null 2>&1; then
    echo "VictorMono Nerd Font already installed."
    return
  fi
  echo -e "\n>>> Installing VictorMono Nerd Font (the prompt glyphs need it)...\n"
  mkdir -p "$dest"
  if curl -fsSL "$NERD_FONT_URL" -o /tmp/VictorMono.zip \
     && unzip -oq -j /tmp/VictorMono.zip '*.ttf' -d "$dest/"; then
    rm -f /tmp/VictorMono.zip
    [ "$os" = "Linux" ] && command -v fc-cache >/dev/null 2>&1 && fc-cache -f "$dest" >/dev/null 2>&1
    echo "VictorMono Nerd Font installed — set your terminal font to 'VictorMono Nerd Font'."
  else
    warn "could not install VictorMono Nerd Font — install one from https://www.nerdfonts.com and select it in your terminal."
  fi
}

### 3.2 fetch the starship config into a temp dir, echo its path
function fetch_config() {
  if [ -n "$STARSHIP_SRC" ]; then
    [ -f "$STARSHIP_SRC/starship.toml" ] \
      || abort "STARSHIP_SRC '$STARSHIP_SRC' must contain starship.toml."
    echo "$STARSHIP_SRC"
    return
  fi
  local tmp src
  tmp=$(mktemp -d)
  curl -fsSL "$STARSHIP_ARCHIVE" | tar xz -C "$tmp" || abort "could not download/extract the config archive."
  src=$(find "$tmp" -type d -name starship -maxdepth 2 | head -n1)
  [ -n "$src" ] && [ -f "$src/starship.toml" ] || abort "could not find the starship/ config inside the archive."
  echo "$src"
}

### 3.3 deploy the config to ~/.config/starship.toml (backing up any existing one)
function deploy_config() {
  local src="$1" target="$HOME/.config/starship.toml"
  mkdir -p "$HOME/.config"
  if [ -e "$target" ] || [ -L "$target" ]; then
    local backup
    backup="$target.bak-$(date +%s)"
    mv "$target" "$backup"
    warn "existing ~/.config/starship.toml moved to $backup"
  fi
  cp "$src/starship.toml" "$target"
  echo "deployed ~/.config/starship.toml"
}

### 3.4 wire 'starship init' into the shell rc files that exist (idempotent)
function wire_shells() {
  local wired=0
  _wire_one bash "$HOME/.bashrc" && wired=1
  _wire_one zsh  "$HOME/.zshrc"  && wired=1
  if [ "$wired" -eq 0 ]; then
    warn "no ~/.bashrc or ~/.zshrc found. Add this to your shell rc by hand:"
    warn "  eval \"\$(starship init <bash|zsh|fish>)\""
  fi
}

### _wire_one: append the init line to one rc file, once (marker-guarded)
function _wire_one() {
  local shell="$1" rc="$2"
  [ -f "$rc" ] || return 1
  # skip if our block is there OR the rc already calls 'starship init' by hand
  # (avoids a duplicate eval on machines that were already set up manually)
  if grep -qF "$MARKER" "$rc" 2>/dev/null || grep -q 'starship init' "$rc" 2>/dev/null; then
    echo "starship init already present in $rc, skipping."
    return 0
  fi
  {
    echo ""
    echo "$MARKER"
    echo "command -v starship >/dev/null 2>&1 && eval \"\$(starship init $shell)\""
  } >> "$rc"
  echo "wired starship into $rc"
  return 0
}

## 4. EXECUTING ###############################################################

check_not_root
need_cmd curl
need_cmd tar

install_starship
install_nerd_font

CONFIG_SRC=$(fetch_config)
deploy_config "$CONFIG_SRC"
wire_shells

## 5. NOTIFICATIONS ###########################################################

echo -e "\n----------------------------------------------------------------------------------"
echo -e "\nAll done! starship is installed and configured."
echo "Config: ~/.config/starship.toml  (gruvbox_dark preset)"
echo -e "\nOpen a new shell (or 'source' your rc) to see the new prompt."
echo "The prompt uses Nerd Font glyphs — set a Nerd Font in your terminal if they"
echo "show as boxes (macOS installs 0xProto Nerd Font for you here)."
echo -e "\nEnjoy it!"
echo -e "\nWant to know more about our collective? Visit https://bolha.io and consider joining us! ;)"
echo -e "Come and visit our mastodon instance:    https://bolha.us"
echo -e "Come and visit our mattermost instance:  https://mattermost.bolha.chat"
echo -e "Say hello on the fediverse:              @gutocarvalho@bolha.us"
echo -e "\n----------------------------------------------------------------------------------\n"
