#!/usr/bin/env bash

# gen-third-party-licenses
#
# Regenerates the committed Go-dependency license fragments:
#
#   lib/wmchat/THIRD_PARTY_LICENSES   (WhatsApp / whatsmeow Go module tree)
#   lib/sgchat/THIRD_PARTY_LICENSES   (Signal / mautrix-signal Go module tree)
#
# These fragments are combined at build time (see the top-level CMakeLists.txt)
# with the hand-maintained fragments (lib/ncutil, lib/tgchat, utils/dist) into
# the THIRD_PARTY_LICENSES file installed alongside binary distributions.
#
# This is a maintainer-only tool, not part of the normal build. Rerun it after
# bumping the whatsmeow / signal dependencies (the whatsmeow-update and
# signal-update scripts print a reminder) and commit the regenerated fragment
# in the same change, so attribution stays in sync with the vendored trees.
#
# Requirements: go and go-licenses on PATH. Install go-licenses with:
#   go install github.com/google/go-licenses@latest
#
# Output is deterministic: modules are listed alphabetically and only verbatim
# license texts (no absolute module-cache paths) are emitted, so regenerating
# from an unchanged dependency set produces a byte-identical file.
#
# Usage:
#   utils/dist/gen-third-party-licenses [wmchat|sgchat|all]   (default: all)
#
# nchat is distributed under the MIT license, see LICENSE for details.

set -euo pipefail

usage() {
  echo "usage: $0 [wmchat|sgchat|all]" >&2
  exit 1
}

REPO_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
SUPPLEMENTS_DIR="${REPO_DIR}/utils/licenses/supplements"

if ! command -v go-licenses >/dev/null 2>&1; then
  echo "$0: go-licenses not found on PATH" >&2
  echo "$0: install it with: go install github.com/google/go-licenses@latest" >&2
  echo "$0: (then ensure \"\$(go env GOPATH)/bin\" is on PATH)" >&2
  exit 1
fi

# gen_fragment <go-dir> <output> <title> <local-prefix> <primary-prefix> \
#              <primary-version> <primary-url>
#
# <local-prefix>    import-path prefix of nchat's own (unlicensed) module,
#                   skipped in the output.
# <primary-prefix>  import-path prefix of the in-tree replaced upstream module
#                   (whatsmeow / mautrix-signal); go-licenses cannot resolve a
#                   version/URL for a local replace, so they are supplied here.
gen_fragment() {
  local godir="$1" output="$2" title="$3" local_prefix="$4"
  local primary_prefix="$5" primary_version="$6" primary_url="$7"

  echo "$0: generating ${output#${REPO_DIR}/}"

  # Tab-separated: name, version, license-name, license-url, license-path.
  local tmpl='{{range .}}{{.Name}}{{"\t"}}{{.Version}}{{"\t"}}{{.LicenseName}}{{"\t"}}{{.LicenseURL}}{{"\t"}}{{.LicensePath}}{{"\n"}}{{end}}'
  local report tmplfile
  report="$(mktemp)"
  tmplfile="$(mktemp)"
  printf '%s' "${tmpl}" > "${tmplfile}"

  # go-licenses logs progress/warnings to stderr (informational; missing-license
  # modules are handled by the supplement fallback below); the template output
  # goes to stdout, which is all that lands in the fragment.
  ( cd "${godir}" && go-licenses report . --template "${tmplfile}" ) > "${report}"
  rm -f "${tmplfile}"

  local out
  out="$(mktemp)"
  {
    printf '%s\n' "================================================================================"
    printf 'nchat third-party licenses: %s\n' "${title}"
    printf '%s\n\n' "================================================================================"
    printf '%s\n' "Auto-generated by utils/dist/gen-third-party-licenses from the Go module"
    printf '%s\n' "dependency tree of ${godir#${REPO_DIR}/}, using go-licenses. Do not edit by"
    printf '%s\n' "hand. One verbatim license text is kept per module; each carries that"
    printf '%s\n' "module's own copyright notice, as MIT/BSD attribution requires."
    printf '\n'
  } > "${out}"

  # LC_ALL=C for a stable, locale-independent sort.
  local name version license url path
  while IFS=$'\t' read -r name version license url path; do
    [[ -z "${name}" ]] && continue
    # Skip nchat's own module (has no license of its own).
    [[ "${name}" == "${local_prefix}"* ]] && continue

    # The in-tree replaced upstream module: supply version/URL go-licenses
    # cannot derive from a local replace directive.
    if [[ -n "${primary_prefix}" && "${name}" == "${primary_prefix}"* ]]; then
      [[ "${version}" == "Unknown" || -z "${version}" ]] && version="${primary_version}"
      url="${primary_url}"
    fi

    # Fall back to a committed supplement when a module ships no license text
    # (some tagged module zips omit it); fail loudly rather than under-attribute.
    if [[ -z "${path}" ]]; then
      local supplement="${SUPPLEMENTS_DIR}/${name}/LICENSE"
      if [[ -f "${supplement}" ]]; then
        path="${supplement}"
        [[ "${url}" == "Unknown" || -z "${url}" ]] && url="https://${name}"
        # Optional SPDX id sidecar (go-licenses cannot classify a module that
        # ships no license text, so it reports the type as Unknown).
        if [[ ( "${license}" == "Unknown" || -z "${license}" ) && -f "${SUPPLEMENTS_DIR}/${name}/SPDX" ]]; then
          license="$(head -n1 "${SUPPLEMENTS_DIR}/${name}/SPDX")"
        fi
      else
        echo "$0: ERROR: no license text for '${name}' and no supplement at" >&2
        echo "$0:        ${supplement#${REPO_DIR}/}" >&2
        echo "$0:        Add the module's verbatim license there and rerun." >&2
        rm -f "${report}" "${out}"
        exit 1
      fi
    fi

    {
      printf '%s\n' "--------------------------------------------------------------------------------"
      printf '%s  %s  (%s)\n' "${name}" "${version}" "${license}"
      [[ "${url}" != "Unknown" && -n "${url}" ]] && printf '%s\n' "${url}"
      printf '%s\n' "--------------------------------------------------------------------------------"
      printf '\n'
      cat "${path}"
      printf '\n\n'
    } >> "${out}"
  done < <(LC_ALL=C sort "${report}")

  mv "${out}" "${output}"
  rm -f "${report}"
}

gen_wmchat() {
  local version
  version="$(awk -F'= ' '/^var whatsmeowDate int/ { print $2; exit }' \
    "${REPO_DIR}/lib/wmchat/go/gowm.go")"
  gen_fragment \
    "${REPO_DIR}/lib/wmchat/go" \
    "${REPO_DIR}/lib/wmchat/THIRD_PARTY_LICENSES" \
    "WhatsApp (whatsmeow) Go module tree" \
    "github.com/d99kris/nchat" \
    "go.mau.fi/whatsmeow" "${version}" "https://github.com/tulir/whatsmeow"
}

gen_sgchat() {
  local version
  version="$(awk -F'= ' '/^var signalDate int/ { print $2; exit }' \
    "${REPO_DIR}/lib/sgchat/go/gosg.go")"
  gen_fragment \
    "${REPO_DIR}/lib/sgchat/go" \
    "${REPO_DIR}/lib/sgchat/THIRD_PARTY_LICENSES" \
    "Signal (mautrix-signal / libsignal) Go module tree" \
    "github.com/d99kris/nchat" \
    "go.mau.fi/mautrix-signal" "${version}" "https://github.com/mautrix/signal"
}

case "${1:-all}" in
  wmchat) gen_wmchat ;;
  sgchat) gen_sgchat ;;
  all) gen_wmchat; gen_sgchat ;;
  -h|--help) usage ;;
  *) usage ;;
esac

echo "$0: done"
