#!/usr/bin/env bash
set -euo pipefail
source "$SHELLOPS_DIR/.envrc"
import "$SHELLOPS_DIR/lib/homebrew/api.sh"
import "$SHELLOPS_DIR/lib/manifest.api.sh"

USAGE="$(cat <<EOF
Generates a Homebrew formula from release tarballs and pushes it to a tap repo.

Flags override manifest.json values. If --name, --version, --description,
--homepage, or --bin are omitted, they fall back to the project manifest.

Usage: action homebrew update-tap [options]

Options:
  --tap-repo <url>       Git clone URL of the tap repository (required).
  --asset-url <url>      Base URL where release tarballs are hosted (required).
  --asset-dir <dir>      Local directory containing tarballs for SHA256 computation (required).
  --name <name>          Formula/binary name. Defaults to manifest command-name.
  --version <version>    Release version. Defaults to manifest stable version.
  --description <text>   One-line description. Defaults to manifest description.
  --homepage <url>       Project homepage URL. Defaults to GitHub repo URL from manifest.
  --license <spdx>       SPDX license identifier. Defaults to MIT.
  --bin <name>           Binary filename to install. Defaults to manifest command-name.
  --branch <branch>      Tap repo branch. Defaults to main.
  -h, --help             Show this help text.
EOF
)"

function main() {
  local tap_repo="" name="" version="" asset_url="" asset_dir=""
  local description="" homepage="" license="MIT" bin_name="" branch="main"

  parse_args tap_repo name version asset_url asset_dir \
    description homepage license bin_name branch "$@"
  apply_manifest_defaults name version description homepage bin_name
  validate_args "$tap_repo" "$asset_url" "$asset_dir" "$name" "$version"

  local metadata
  metadata="$(homebrew_build_metadata "$name" "$version" "$description" "$homepage" "$license" "$bin_name")"

  local formula_rb
  formula_rb="$(homebrew_generate_formula "$metadata" "$asset_url" "$asset_dir")"

  local options
  options="$(jq_obj '.branch' "$branch")"

  homebrew_update_tap "$tap_repo" "$formula_rb" "$name" "$version" "$options"
}

function apply_manifest_defaults() {
  local -n _name=$1 _version=$2 _description=$3 _homepage=$4 _bin_name=$5

  [[ -z "$_name" ]]        && _name="$(manifest_get command_name 2>/dev/null || true)"
  [[ -z "$_version" ]]     && _version="$(manifest_get stable 2>/dev/null || true)"
  [[ -z "$_description" ]] && _description="$(manifest_get description 2>/dev/null || true)"
  [[ -z "$_bin_name" ]]    && _bin_name="$(manifest_get command_name 2>/dev/null || true)"

  if [[ -z "$_homepage" ]]; then
    local org repo
    org="$(manifest_get org 2>/dev/null || true)"
    repo="$(manifest_get repo 2>/dev/null || true)"
    [[ -n "$org" && -n "$repo" ]] && _homepage="https://github.com/${org}/${repo}"
  fi
}

function validate_args() {
  local tap_repo="$1" asset_url="$2" asset_dir="$3" name="$4" version="$5"
  local missing=""

  [[ -z "$tap_repo" ]]  && missing="${missing}  --tap-repo\n"
  [[ -z "$asset_url" ]] && missing="${missing}  --asset-url\n"
  [[ -z "$asset_dir" ]] && missing="${missing}  --asset-dir\n"
  [[ -z "$name" ]]      && missing="${missing}  --name (not in manifest either)\n"
  [[ -z "$version" ]]   && missing="${missing}  --version (not in manifest either)\n"

  if [[ -n "$missing" ]]; then
    error "missing required options:"
    echo -e "$missing" >&2
    log "$USAGE"
    exit 1
  fi
}

function parse_args() {
  local -n _tap_repo=$1 _name=$2 _version=$3 _asset_url=$4 _asset_dir=$5
  local -n _description=$6 _homepage=$7 _license=$8 _bin_name=$9
  shift 9
  local -n _branch=$1
  shift

  while [[ $# -gt 0 ]]; do
    case "$1" in
      -h|--help)      log "$USAGE"; exit 0 ;;
      --tap-repo)     _tap_repo="$2"; shift ;;
      --name)         _name="$2"; shift ;;
      --version)      _version="$2"; shift ;;
      --asset-url)    _asset_url="$2"; shift ;;
      --asset-dir)    _asset_dir="$2"; shift ;;
      --description)  _description="$2"; shift ;;
      --homepage)     _homepage="$2"; shift ;;
      --license)      _license="$2"; shift ;;
      --bin)          _bin_name="$2"; shift ;;
      --branch)       _branch="$2"; shift ;;
      -*)
        error "Unknown option: $1"
        exit 1
        ;;
    esac
    shift
  done
}

if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  main "$@"
fi
