#!/usr/bin/env bash
# vicebuild-macos.sh
# Mac test build for Color 64 / BBS-on-a-stick VICE ACIA Fix environment
#
# Based on the Linux vicebuild.sh flow by Al Derosa (Bucko) for the BBS on a Stick project.
# Please keep original project attribution with distributed builds.
#
# What this script does:
#   1) Verifies macOS + Xcode Command Line Tools
#   2) Installs Homebrew if missing and sudo/admin access is available
#   3) Installs build dependencies through Homebrew
#   4) Builds tcpser, if a ./tcpser directory exists beside this script
#   5) Checks out VICE trunk from SourceForge SVN
#   6) Copies ACIA Fix source files into the VICE source tree
#   7) Builds VICE with SDL2 UI
#   8) Installs into $HOME/vice-acia by default, avoiding /usr/local system installs
#   9) Verifies tcpser and x64sc are callable
#
# Usage:
#   chmod +x vicebuild-macos.sh
#   ./vicebuild-macos.sh
#
# Optional environment variables:
#   PREFIX="$HOME/vice-acia" ./vicebuild-macos.sh
#   WORKDIR="$HOME/myworkdir" ./vicebuild-macos.sh
#   VICE_SVN_URL="https://svn.code.sf.net/p/vice-emu/code/trunk" ./vicebuild-macos.sh
#   AUTO_INSTALL_HOMEBREW=0 ./vicebuild-macos.sh
#
# Notes:
#   - Homebrew installs into /opt/homebrew on Apple Silicon and /usr/local on Intel.
#   - This is intentionally separate from the Linux installer script.
#   - First run may take a while because VICE is built from source.

set -euo pipefail

# ---- Resolve script directory and defaults ----
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
PREFIX="${PREFIX:-$HOME/vice-acia}"
WORKDIR="${WORKDIR:-$HOME/myworkdir}"
VICE_SVN_URL="${VICE_SVN_URL:-https://svn.code.sf.net/p/vice-emu/code/trunk}"
VICE_TREE="$WORKDIR/vice-trunk/vice"
TCP_INSTALL="$PREFIX/bin/tcpser_1.1.5"
AUTO_INSTALL_HOMEBREW="${AUTO_INSTALL_HOMEBREW:-1}"

# ---- Helpers ----
have_cmd() { command -v "$1" >/dev/null 2>&1; }

die() {
  echo "ERROR: $*" >&2
  exit 1
}

info() {
  echo
  echo "==> $*"
}

refresh_shell_hash() {
  hash -r 2>/dev/null || true
}

setup_brew_env() {
  local brew_bin=""

  if have_cmd brew; then
    brew_bin="$(command -v brew)"
  elif [[ -x /opt/homebrew/bin/brew ]]; then
    brew_bin="/opt/homebrew/bin/brew"
  elif [[ -x /usr/local/bin/brew ]]; then
    brew_bin="/usr/local/bin/brew"
  fi

  if [[ -n "$brew_bin" ]]; then
    eval "$("$brew_bin" shellenv 2>/dev/null || true)"
    export PATH="$(dirname "$brew_bin"):$PATH"
    refresh_shell_hash
  fi
}

append_path_hint() {
  local shell_rc=""
  case "${SHELL:-}" in
    */zsh) shell_rc="$HOME/.zprofile" ;;
    */bash) shell_rc="$HOME/.bash_profile" ;;
    *) shell_rc="$HOME/.zprofile" ;;
  esac

  if [[ ":$PATH:" != *":$PREFIX/bin:"* ]]; then
    echo
    echo "NOTE: $PREFIX/bin is not currently in PATH."
    echo "You can add it with:"
    echo "  echo 'export PATH=\"$PREFIX/bin:\$PATH\"' >> \"$shell_rc\""
    echo "  source \"$shell_rc\""
    export PATH="$PREFIX/bin:$PATH"
  fi
}

# ---- Platform checks ----
detect_macos() {
  [[ "$(uname -s)" == "Darwin" ]] || die "This script is for macOS only. Detected: $(uname -s)"
  info "Detected macOS $(sw_vers -productVersion) on $(uname -m)"
}

ensure_xcode_tools() {
  info "Checking Xcode command line tools"

  if ! xcode-select -p >/dev/null 2>&1; then
    echo "Xcode Command Line Tools not found."
    echo "Launching Apple installer..."
    xcode-select --install || true
    echo
    echo "IMPORTANT: Complete the Apple Xcode Command Line Tools installation, then rerun this script."
    exit 1
  fi

  echo "Xcode Command Line Tools detected."
}

ensure_homebrew() {
  info "Checking Homebrew"
  setup_brew_env

  if ! have_cmd brew; then
    echo "Homebrew was not found."

    if [[ "$AUTO_INSTALL_HOMEBREW" != "1" ]]; then
      cat <<'HOMEBREW_MANUAL'

Install Homebrew manually from:
  https://brew.sh

Then rerun this script.
HOMEBREW_MANUAL
      exit 1
    fi

    if ! sudo -v >/dev/null 2>&1; then
      cat <<'HOMEBREW_SUDO'

ERROR: Homebrew requires Administrator/sudo access on macOS.

Options:
  1) Log in as an Administrator account and rerun this script.
  2) Install Homebrew manually from https://brew.sh using an Administrator account.
  3) Ask the Mac owner/admin to install Homebrew.
HOMEBREW_SUDO
      exit 1
    fi

    echo "Installing Homebrew..."
    NONINTERACTIVE=1 /bin/bash -c \
      "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

    setup_brew_env

    if ! have_cmd brew; then
      die "Homebrew installation finished, but brew is not available in PATH. Try opening a new Terminal window and rerun this script."
    fi
  fi

  setup_brew_env
  echo "Homebrew detected: $(brew --version | head -n 1)"
  echo "Homebrew prefix: $(brew --prefix)"
}

# ---- Dependencies ----
brew_install_deps() {
  info "Installing build dependencies with Homebrew"

  # Do NOT include libevdev here. It is Linux-only and causes Homebrew to abort on macOS.
  # Homebrew's pkg-config package provides the pkg-config command.
  local packages=(
    subversion
    autoconf
    automake
    bison
    flex
    xa
    pkg-config
    texinfo
    dos2unix
    sdl2
    sdl2_image
    readline
    giflib
    jpeg-turbo
    libpng
    libpcap
    curl
    make
  )

  brew update
  brew install "${packages[@]}"

  # Homebrew bison/flex/texinfo/make can be keg-only or shadowed by Apple tools.
  for opt in bison flex texinfo make; do
    local opt_prefix=""
    opt_prefix="$(brew --prefix "$opt" 2>/dev/null || true)"
    if [[ -n "$opt_prefix" && -d "$opt_prefix/bin" ]]; then
      export PATH="$opt_prefix/bin:$PATH"
    fi
  done

  export PKG_CONFIG_PATH="$(brew --prefix)/lib/pkgconfig:$(brew --prefix)/share/pkgconfig:${PKG_CONFIG_PATH:-}"
  export CPPFLAGS="-I$(brew --prefix)/include ${CPPFLAGS:-}"
  export LDFLAGS="-L$(brew --prefix)/lib ${LDFLAGS:-}"

  refresh_shell_hash
  echo "Using PATH: $PATH"

  info "Verifying required build tools"
  local required_tools=(
    svn
    autoconf
    automake
    bison
    flex
    xa
    pkg-config
    make
  )

  local missing=0
  for tool in "${required_tools[@]}"; do
    if have_cmd "$tool"; then
      echo "  OK: $tool -> $(command -v "$tool")"
    else
      echo "  MISSING: $tool"
      missing=1
    fi
  done

  [[ "$missing" -eq 0 ]] || die "One or more required build tools are missing after Homebrew install."
}

# ---- tcpser ----
build_tcpser() {
  if [[ ! -d "$SCRIPT_DIR/tcpser" ]]; then
    echo
    echo "NOTE: No tcpser directory found beside this script."
    echo "Skipping tcpser build."
    echo "Expected: $SCRIPT_DIR/tcpser"
    return 0
  fi

  info "Building tcpser"
  mkdir -p "$PREFIX/bin"

  cd "$SCRIPT_DIR/tcpser"
  make clean || true
  make

  [[ -x ./tcpser ]] || die "tcpser build did not produce ./tcpser"

  cp ./tcpser "$TCP_INSTALL"
  chmod +x "$TCP_INSTALL"
  ln -sf "$TCP_INSTALL" "$PREFIX/bin/tcpser"

  echo "Installed tcpser to: $TCP_INSTALL"

  info "Running tcpser smoke test"
  set +e
  "$PREFIX/bin/tcpser" -v 1 -p 6502 -s 38400 -l 4 >/tmp/tcpser-smoke.log 2>&1 &
  local pid=$!
  sleep 1
  if kill -0 "$pid" >/dev/null 2>&1; then
    echo "tcpser smoke test started on port 6502, then stopped."
    kill "$pid" >/dev/null 2>&1 || true
    wait "$pid" 2>/dev/null || true
  else
    echo "tcpser exited during smoke test. See /tmp/tcpser-smoke.log"
    cat /tmp/tcpser-smoke.log || true
  fi
  set -e
}

# ---- VICE checkout and patch ----
checkout_vice() {
  info "Checking out/updating VICE source"
  mkdir -p "$WORKDIR"
  cd "$WORKDIR"

  if [[ -d "$WORKDIR/vice-trunk/.svn" ]]; then
    svn update "$WORKDIR/vice-trunk"
  else
    rm -rf "$WORKDIR/vice-trunk"
    svn checkout "$VICE_SVN_URL" vice-trunk
  fi

  [[ -d "$VICE_TREE/src" ]] || die "VICE source tree not found at $VICE_TREE"
}

find_aciafix_dir() {
  local found=""

  if [[ -d "$SCRIPT_DIR/aciafix" ]]; then
    found="$SCRIPT_DIR/aciafix"
  else
    found="$(find "$SCRIPT_DIR" "$WORKDIR" "$HOME" -maxdepth 4 -type d -name aciafix -print -quit 2>/dev/null || true)"
  fi

  [[ -n "$found" ]] || die "Could not locate directory named 'aciafix'. Expected it near the script, workdir, or home directory."
  echo "$found"
}

patch_vice_acia() {
  local aciafix_dir="$1"

  info "Copying ACIA Fix files from: $aciafix_dir"

  local required=(
    aciacore.c
    rs232.c
    rs232.h
    rs232net.c
    rs232net.h
  )

  for f in "${required[@]}"; do
    [[ -f "$aciafix_dir/$f" ]] || die "Missing ACIA Fix file: $aciafix_dir/$f"
  done

  cp -p "$aciafix_dir/aciacore.c" "$VICE_TREE/src/"
  cp -p "$aciafix_dir/rs232.c"    "$VICE_TREE/src/rs232drv/"
  cp -p "$aciafix_dir/rs232.h"    "$VICE_TREE/src/rs232drv/"
  cp -p "$aciafix_dir/rs232net.c" "$VICE_TREE/src/rs232drv/"
  cp -p "$aciafix_dir/rs232net.h" "$VICE_TREE/src/rs232drv/"
}

# ---- VICE build ----
build_vice() {
  info "Building VICE with SDL2 UI"
  cd "$VICE_TREE"

  ./autogen.sh

  ./configure \
    --prefix="$PREFIX" \
    --enable-sdl2ui \
    --with-sdlsound \
    --without-png

  make
  make install
}

verify_bins() {
  info "Verifying installed binaries"
  append_path_hint

  if [[ -x "$PREFIX/bin/x64sc" ]]; then
    echo "x64sc installed: $PREFIX/bin/x64sc"
    "$PREFIX/bin/x64sc" -version || true
  else
    die "x64sc was not found at $PREFIX/bin/x64sc after install."
  fi

  if [[ -x "$PREFIX/bin/tcpser" ]]; then
    echo "tcpser installed: $PREFIX/bin/tcpser"
  else
    echo "NOTE: tcpser was not installed because no tcpser source directory was found or build failed."
  fi

  cat <<EOF

Build complete.

To use this build in the current terminal:
  export PATH="$PREFIX/bin:\$PATH"

VICE:
  x64sc -version

TCPSER example:
  tcpser -p 8502 -l 4 -v 25237 -s 38400 -A answer.txt -C connect.txt -N noanswer.txt -B busy.txt

Color 64 launch scripts on macOS should call:
  $PREFIX/bin/x64sc

EOF
}

main() {
  detect_macos
  ensure_xcode_tools
  ensure_homebrew
  brew_install_deps
  build_tcpser
  checkout_vice
  local aciafix_dir
  aciafix_dir="$(find_aciafix_dir)"
  patch_vice_acia "$aciafix_dir"
  build_vice
  verify_bins
}

main "$@"
