#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VENV_PYTHON="$SCRIPT_DIR/.venv/bin/python3"

if [ -f "$SCRIPT_DIR/.env" ]; then
	# shellcheck source=/dev/null
	source "$SCRIPT_DIR/.env"
fi

init_paper() {
	local raw="${1:-.}"
	local name
	name="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]' | tr -d '\\' | tr '[:space:]' '_')"
	local dest="$SCRIPT_DIR/papers/$name"
	if [ -d "$dest" ]; then
		echo "Error: '$dest' already exists" >&2
		exit 1
	fi
	mkdir -p "$dest"
	cp "$SCRIPT_DIR/ams-latex-template/doc/amsart-template.tex" "$dest/paper.tex"
	sed -i '' "s|\\\\title{}|\\\\title{$raw}|" "$dest/paper.tex"
	sed -i '' "s|\\\\author{}|\\\\author{Eric Bauerfeld}|" "$dest/paper.tex"
	sed -i '' '/^%    author two information$/,/^\\thanks{}$/d' "$dest/paper.tex"
	echo "Initialized paper.tex in $dest"
}

setup() {
	local sage_python_path="${1:-${SAGE_PYTHON_PATH:?Usage: setup <sage_python_path> <sage_site_packages> <system_name>}}"
	local sage_site_packages="${2:-${SAGE_SITE_PACKAGES:?Usage: setup <sage_python_path> <sage_site_packages> <system_name>}}"
	local system_name="${3:-$(hostname -s)}"

	printf 'SAGE_PYTHON_PATH=%s\nSAGE_SITE_PACKAGES=%s\n' "$sage_python_path" "$sage_site_packages" \
		>"$SCRIPT_DIR/.env.$system_name"
	ln -sf ".env.$system_name" "$SCRIPT_DIR/.env"
	source "$SCRIPT_DIR/.env"

	mkdir -p "$SCRIPT_DIR/.vscode"
	"$sage_python_path" - <<EOF
import json
settings = {
    "python.defaultInterpreterPath": "$sage_python_path",
    "python.analysis.extraPaths": ["$sage_site_packages"],
    "python.analysis.diagnosticSeverityOverrides": {
        "reportUnknownMemberType": "warning",
        "reportUnknownArgumentType": "warning",
        "reportUnknownParameterType": "warning",
        "reportMissingParameterType": "warning",
        "reportUnknownVariableType": "warning"
    }
}
with open("$SCRIPT_DIR/.vscode/settings.json", "w") as f:
    json.dump(settings, f, indent=4)
    f.write("\n")
EOF

	if command -v nix-shell &>/dev/null; then
		nix-shell -p gcc --run "make -C \"$SCRIPT_DIR/plantri\""
	else
		make -C "$SCRIPT_DIR/plantri"
	fi

	"$sage_python_path" -m venv "$SCRIPT_DIR/.venv"
	"$VENV_PYTHON" -m pip install -r "$SCRIPT_DIR/requirements.txt"
}

run_sage() {
	PATH="$PATH:$SCRIPT_DIR/plantri" sage "$@"
}

lint() {
	local path="${1:-lib/}"
	"$VENV_PYTHON" -m pyright "$path" --pythonpath "$SAGE_PYTHON_PATH"
	"$VENV_PYTHON" -m pylint "$path" \
		--init-hook="import sys; sys.path.insert(0, '${SAGE_SITE_PACKAGES}'); sys.path.insert(0, '${SCRIPT_DIR}')" \
		--disable=fixme
}

completion() {
	local shell="${1:-zsh}"
	case "$shell" in
	zsh)
		cat <<'EOF'
_run_sh() {
  local curcontext="$curcontext" state line
  typeset -A opt_args

  _arguments -C \
    '1: :->subcmd' \
    '*: :->args'

  case $state in
    subcmd)
      local subcmds=(
        'init_paper:Initialize a new paper directory from the AMS template'
        'setup:Configure Python/Sage environment and install dependencies'
        'sage:Run sage with plantri available on PATH'
        'lint:Run pyright and pylint on lib/'
        'completion:Output shell completion code'
      )
      _describe 'subcommand' subcmds
      ;;
    args)
      case $words[2] in
        init_paper)
          _message 'paper title (spaces become underscores)'
          ;;
        setup)
          case $((CURRENT - 2)) in
            1) _files ;;
            2) _files -/ ;;
            3) _message 'system name (e.g. macbook, workstation)' ;;
          esac
          ;;
        sage)
          _files
          ;;
        lint)
          _files
          ;;
        completion)
          _values 'shell' 'zsh' 'bash'
          ;;
      esac
      ;;
  esac
}

compdef _run_sh run.sh
EOF
		;;
	bash)
		cat <<'EOF'
_run_sh() {
  local cur prev words cword
  _init_completion || return

  local subcmds='init_paper setup sage lint completion'

  if [[ $cword -eq 1 ]]; then
    COMPREPLY=( $(compgen -W "$subcmds" -- "$cur") )
    return
  fi

  case ${words[1]} in
    init_paper)
      # free-form paper title, no completion
      ;;
    setup)
      case $((cword - 1)) in
        1) COMPREPLY=( $(compgen -f -- "$cur") ) ;;
        2) COMPREPLY=( $(compgen -d -- "$cur") ) ;;
        3) COMPREPLY=() ;;  # system name, free-form
      esac
      ;;
    sage|lint)
      COMPREPLY=( $(compgen -f -- "$cur") )
      ;;
    completion)
      COMPREPLY=( $(compgen -W 'zsh bash' -- "$cur") )
      ;;
  esac
}

complete -F _run_sh run.sh
EOF
		;;
	*)
		echo "Unsupported shell: $shell. Supported: zsh bash" >&2
		exit 1
		;;
	esac
}

case "${1:-}" in
init_paper)
	shift
	init_paper "$@"
	;;
setup)
	shift
	setup "$@"
	;;
sage)
	shift
	run_sage "$@"
	;;
lint)
	shift
	lint "$@"
	;;
completion)
	shift
	completion "$@"
	;;
*)
	echo "Usage: $0 {init_paper|setup|sage|lint|completion} [args]" >&2
	exit 1
	;;
esac
