#!/bin/sh
# Code generated by binstaller. DO NOT EDIT.
# This script runs ghcp directly without installing
#
set -e
usage() {
  this=$1
  cat <<EOF
$this: download and run ${NAME} from ${REPO}

Usage: $this [-d] [tag] -- [binary arguments]
  -d turns on debug logging
   [tag] is a tag from
   https://github.com/int128/ghcp/releases
   If tag is missing, then latest will be used.

   This script downloads and runs ghcp directly
   Pass arguments after --:
   Example: $this -- --help
   Example: $this -- --version

 Generated by binstaller
  https://github.com/binary-install/binstaller
EOF
  exit 2
}

cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
  command -v "$1" >/dev/null
}
echoerr() {
  echo "$@" 1>&2
}
_logp=6
log_set_priority() {
  _logp="$1"
}
log_priority() {
  if test -z "$1"; then
    echo "$_logp"
    return
  fi
  [ "$1" -le "$_logp" ]
}
log_tag() {
  case $1 in
    0) echo "emerg" ;;
    1) echo "alert" ;;
    2) echo "crit" ;;
    3) echo "err" ;;
    4) echo "warning" ;;
    5) echo "notice" ;;
    6) echo "info" ;;
    7) echo "debug" ;;
    *) echo "$1" ;;
  esac
}
log_debug() {
  log_priority 7 || return 0
  echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
  log_priority 6 || return 0
  echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
  log_priority 3 || return 0
  echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
  log_priority 2 || return 0
  echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
  os=$(uname -s | tr '[:upper:]' '[:lower:]')
  case "$os" in
    msys*) os="windows" ;;
    mingw*) os="windows" ;;
    cygwin*) os="windows" ;;
  esac
  if [ "$os" = "sunos" ]; then
    if [ "$(uname -o)" = "illumos" ]; then
      os="illumos"
    else
      os="solaris"
    fi
  fi
  echo "$os"
}
uname_arch() {
  arch=$(uname -m)
  case $arch in
    x86_64) arch="amd64" ;;
    i86pc) arch="amd64" ;;
    x86) arch="386" ;;
    i686) arch="386" ;;
    i386) arch="386" ;;
    aarch64) arch="arm64" ;;
    armv5*) arch="armv5" ;;
    armv6*) arch="armv6" ;;
    armv7*) arch="armv7" ;;
  esac
  echo "${arch}"
}
uname_os_check() {
  os=$(uname_os)
  case "$os" in
    darwin) return 0 ;;
    dragonfly) return 0 ;;
    freebsd) return 0 ;;
    linux) return 0 ;;
    android) return 0 ;;
    midnightbsd) return 0 ;;
    nacl) return 0 ;;
    netbsd) return 0 ;;
    openbsd) return 0 ;;
    plan9) return 0 ;;
    solaris) return 0 ;;
    illumos) return 0 ;;
    windows) return 0 ;;
  esac
  log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
  return 1
}
uname_arch_check() {
  arch=$(uname_arch)
  case "$arch" in
    386) return 0 ;;
    amd64) return 0 ;;
    arm64) return 0 ;;
    armv5) return 0 ;;
    armv6) return 0 ;;
    armv7) return 0 ;;
    ppc64) return 0 ;;
    ppc64le) return 0 ;;
    mips) return 0 ;;
    mipsle) return 0 ;;
    mips64) return 0 ;;
    mips64le) return 0 ;;
    s390x) return 0 ;;
    amd64p32) return 0 ;;
  esac
  log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value.  Please file bug report at https://github.com/client9/shlib"
  return 1
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF


hash_sha256() {
  TARGET=${1:-/dev/stdin}
  if is_command gsha256sum; then
    hash=$(gsha256sum "$TARGET") || return 1
    echo "$hash" | cut -d ' ' -f 1
  elif is_command sha256sum; then
    hash=$(sha256sum "$TARGET") || return 1
    echo "$hash" | cut -d ' ' -f 1
  elif is_command shasum; then
    hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
    echo "$hash" | cut -d ' ' -f 1
  elif is_command openssl; then
    hash=$(openssl dgst -sha256 "$TARGET") || return 1
    echo "$hash" | cut -d ' ' -f 2
  else
    log_crit "hash_sha256 unable to find command to compute sha-256 hash"
    return 1
  fi
}

hash_compute() {
  hash_sha256 "$1"
}


untar() {
  tarball=$1
  strip_components=${2:-0} # default 0
  case "${tarball}" in
  *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" --strip-components "${strip_components}" ;;
  *.tar.xz) tar --no-same-owner -xJf "${tarball}" --strip-components "${strip_components}" ;;
  *.tar.bz2) tar --no-same-owner -xjf "${tarball}" --strip-components "${strip_components}" ;;
  *.tar) tar --no-same-owner -xf "${tarball}" --strip-components "${strip_components}" ;;
  *.gz) gunzip "${tarball}" ;;
  *.zip)
    # unzip doesn't have a standard --strip-components
    # Workaround: extract to a subdir and move contents up if stripping
    if [ "$strip_components" -gt 0 ]; then
      extract_dir=$(basename "${tarball%.zip}")_extracted
      unzip -q "${tarball}" -d "${extract_dir}"
      # Move contents of the *first* directory found inside extract_dir up
      # This assumes wrap_in_directory=true convention
      first_subdir=$(find "${extract_dir}" -mindepth 1 -maxdepth 1 -type d -print -quit)
      if [ -n "$first_subdir" ]; then
        # Move all contents (* includes hidden files)
        mv "${first_subdir}"/* .
        # Optionally remove the now-empty subdir and the extract_dir
        rmdir "${first_subdir}"
        rmdir "${extract_dir}"
      else
        log_warn "Could not find subdirectory in zip to strip components from ${extract_dir}"
        # Files are extracted in current dir anyway, proceed
      fi
    else
      unzip -q "${tarball}"
    fi
    ;;
  *)
    log_err "untar unknown archive format for ${tarball}"
    return 1
    ;;
  esac
}



hash_verify() {
  TARGET_PATH=$1
  SUMFILE=$2
  if [ -z "${SUMFILE}" ]; then
    log_err "hash_verify checksum file not specified in arg2"
    return 1
  fi
  got=$(hash_compute "$TARGET_PATH")
  if [ -z "${got}" ]; then
    log_err "failed to calculate hash: ${TARGET_PATH}"
    return 1
  fi

  BASENAME=${TARGET_PATH##*/}

  # Check for line matches in checksum file
  # Format: "<hash>  <filename>" or "<hash> *<filename>"
  # Filename may include path prefix (e.g., "deployment/m2/file.tar.gz")
  while IFS= read -r line || [ -n "$line" ]; do
    # Normalize tabs to spaces
    line=$(echo "$line" | tr '\t' ' ')

    # Remove trailing spaces for hash-only line check
    line_trimmed=$(echo "$line" | sed 's/[[:space:]]*$//')

    # Check for hash-only line (no filename) - early return
    if [ "$line_trimmed" = "$got" ]; then
      return 0
    fi

    # Extract hash and filename parts
    # First field is the hash, rest is filename (which may contain spaces)
    line_hash=$(echo "$line" | cut -d' ' -f1)

    # Skip if hash doesn't match
    if [ "$line_hash" != "$got" ]; then
      continue
    fi

    # Hash matches, now check filename
    # Remove the hash part from the beginning of the line
    line_rest="${line#"$got"}"
    # Remove leading spaces
    while [ "${line_rest#[ ]}" != "$line_rest" ]; do
      line_rest="${line_rest#[ ]}"
    done

    # Remove leading asterisk if present (binary mode indicator)
    if [ "${line_rest#\*}" != "$line_rest" ]; then
      line_rest="${line_rest#\*}"
    fi

    # Extract just the filename without any path
    line_filename="${line_rest##*/}"

    # Check if the filename matches
    if [ "$line_filename" = "$BASENAME" ]; then
      return 0
    fi
  done < "$SUMFILE"

  log_err "hash_verify checksum for '$TARGET_PATH' did not verify"
  log_err "  Expected hash: ${got}"
  log_err "  Checksum file content:"
  cat "$SUMFILE" >&2
  return 1
}

# GitHub HTTP download functions with GITHUB_TOKEN support
github_http_download_curl() {
  local_file=$1
  source_url=$2
  header=$3
  if [ -n "$GITHUB_TOKEN" ]; then
    log_debug "Using GITHUB_TOKEN for authentication"
    if [ -z "$header" ]; then
      curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -o "$local_file" "$source_url"
    else
      curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "$header" -o "$local_file" "$source_url"
    fi
  else
    if [ -z "$header" ]; then
      curl -fsSL -o "$local_file" "$source_url"
    else
      curl -fsSL -H "$header" -o "$local_file" "$source_url"
    fi
  fi
}
github_http_download_wget() {
  local_file=$1
  source_url=$2
  header=$3
  if [ -n "$GITHUB_TOKEN" ]; then
    log_debug "Using GITHUB_TOKEN for authentication"
    if [ -z "$header" ]; then
      wget -q --header "Authorization: Bearer $GITHUB_TOKEN" -O "$local_file" "$source_url"
    else
      wget -q --header "Authorization: Bearer $GITHUB_TOKEN" --header "$header" -O "$local_file" "$source_url"
    fi
  else
    if [ -z "$header" ]; then
      wget -q -O "$local_file" "$source_url"
    else
      wget -q --header "$header" -O "$local_file" "$source_url"
    fi
  fi
}
github_http_download() {
  log_debug "github_http_download $2"
  if is_command curl; then
    github_http_download_curl "$@"
    return
  elif is_command wget; then
    github_http_download_wget "$@"
    return
  fi
  log_crit "github_http_download unable to find wget or curl"
  return 1
}
github_http_copy() {
  tmp=$(mktemp)
  github_http_download "${tmp}" "$@" || return 1
  body=$(cat "$tmp")
  rm -f "${tmp}"
  echo "$body"
}
github_release() {
  owner_repo=$1
  version=$2
  test -z "$version" && version="latest"
  giturl="https://github.com/${owner_repo}/releases/${version}"
  json=$(github_http_copy "$giturl" "Accept:application/json")
  test -z "$json" && return 1
  version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
  test -z "$version" && return 1
  echo "$version"
}

# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
EMBEDDED_CHECKSUMS="
1.15.0:ghcp_darwin_amd64.zip:bbfc2198a03e72724d8d4a69290c63ee795a7272c94e23cddb723a389b49e03e
1.15.0:ghcp_darwin_arm64.zip:9c5098814639ec85bce76283980b6e8cbda9cfba334c360f542f993800d0c507
1.15.0:ghcp_linux_amd64.zip:7793962ce99e3ce153a691565d6904743995d922f8d452427c5ec066bd71e0d0
1.15.0:ghcp_linux_arm.zip:6fb501180eab0413f14161c739f148a59b56dec782141a2dfe60d44166173275
1.15.0:ghcp_linux_arm64.zip:bf2d2b54a848a1c10aa751d52f7fa5af3e147a459514522c5a0a1fa8a43457ce
1.15.0:ghcp_windows_amd64.zip:f6e3a8296ec17cdb3092660dfca3781d53644e0d05b5706a9b00076c11fb6cec"

# Find embedded checksum for a given version and filename
find_embedded_checksum() {
  version="$1"
  filename="$2"
  echo "$EMBEDDED_CHECKSUMS" | grep -E "^${version}:${filename}:" | cut -d':' -f3
}
parse_args() {
  PARSE_CONSUMED=0
  while [ $# -gt 0 ]; do
    case "$1" in
    -d)
      log_set_priority 10
      PARSE_CONSUMED=$((PARSE_CONSUMED+1))
      ;;
    -h | --help | \?)
      usage "$0"
      ;;
    -x)
      set -x
      PARSE_CONSUMED=$((PARSE_CONSUMED+1))
      ;;
    --)
      PARSE_CONSUMED=$((PARSE_CONSUMED+1))
      shift
      break
      ;;
    -*)
      usage "$0"
      ;;
    *)
      # First non-flag argument is the tag/version
      TAG="$1"
      PARSE_CONSUMED=$((PARSE_CONSUMED+1))
      ;;
    esac
    shift
  done
  TAG="${TAG:-latest}"
}
tag_to_version() {
  if [ "$TAG" = "latest" ]; then
    log_info "checking GitHub for latest tag"
    REALTAG=$(github_release "${REPO}" "${TAG}") && true
    test -n "$REALTAG" || {
      log_crit "Could not determine latest tag for ${REPO}"
      exit 1
    }
  else
    # Assume TAG is a valid tag/version string
    REALTAG="$TAG"
  fi
  if test -z "$REALTAG"; then
    log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${REPO}/releases for details"
    exit 1
  fi
  VERSION=${REALTAG#v} # Strip leading 'v'
  TAG="$REALTAG"       # Use the resolved tag
  log_info "Resolved version: ${VERSION} (tag: ${TAG})"
}



resolve_asset_filename() {

  # --- Apply Rules ---
  ASSET_FILENAME=""
  if [ -z "${ASSET_FILENAME}" ]; then
    ASSET_FILENAME="ghcp_${OS}_${ARCH}${EXT}"
  fi
}
# Cleanup function to remove temporary files
cleanup() {
  if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
    log_debug "Cleaning up temporary directory: $TMPDIR"
    rm -rf -- "$TMPDIR"
  fi
}

execute() {
  STRIP_COMPONENTS=0
  CHECKSUM_FILENAME="${ASSET_FILENAME}.sha256"

  # --- Construct URLs ---
  GITHUB_DOWNLOAD="https://github.com/${REPO}/releases/download"
  ASSET_URL="${GITHUB_DOWNLOAD}/${TAG}/${ASSET_FILENAME}"
  CHECKSUM_URL=""
  if [ -n "$CHECKSUM_FILENAME" ]; then
    CHECKSUM_URL="${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM_FILENAME}"
  fi

  # --- Download and Verify ---
  TMPDIR=$(mktemp -d)
  trap cleanup EXIT HUP INT TERM
  log_debug "Downloading files into ${TMPDIR}"
  log_info "Downloading ${ASSET_URL}"
  github_http_download "${TMPDIR}/${ASSET_FILENAME}" "${ASSET_URL}"

  # Try to find embedded checksum first
  EMBEDDED_HASH=$(find_embedded_checksum "$VERSION" "$ASSET_FILENAME")

  if [ -n "$EMBEDDED_HASH" ]; then
    log_info "Using embedded checksum for verification"

    # Verify using embedded hash
    got=$(hash_compute "${TMPDIR}/${ASSET_FILENAME}")
    if [ "$got" != "$EMBEDDED_HASH" ]; then
      log_crit "Checksum verification failed for ${ASSET_FILENAME}"
      log_crit "Expected: ${EMBEDDED_HASH}"
      log_crit "Got: ${got}"
      return 1
    fi
    log_info "Checksum verification successful"
  elif [ -n "$CHECKSUM_URL" ]; then
    # Fall back to downloading checksum file
    log_info "Downloading checksums from ${CHECKSUM_URL}"
    github_http_download "${TMPDIR}/${CHECKSUM_FILENAME}" "${CHECKSUM_URL}"
    log_info "Verifying checksum ..."
    hash_verify "${TMPDIR}/${ASSET_FILENAME}" "${TMPDIR}/${CHECKSUM_FILENAME}"
  else
    log_info "No checksum found, skipping verification."
  fi

  if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
    log_debug "Target is raw binary"
  else
    log_info "Extracting ${ASSET_FILENAME}..."
    (cd "${TMPDIR}" && untar "${ASSET_FILENAME}" "${STRIP_COMPONENTS}")
  fi
  BINARY_NAME='ghcp'
  if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
    BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
  else
    BINARY_PATH="${TMPDIR}/ghcp"
  fi

  if [ "${UNAME_OS}" = "windows" ]; then
    case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
    case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
  fi

  if [ ! -f "${BINARY_PATH}" ]; then
    log_crit "Binary not found: ${BINARY_PATH}"
    log_crit "Listing contents of ${TMPDIR} ..."
    if command -v find >/dev/null 2>&1; then
      cd "${TMPDIR}" && find .
    else
      cd "${TMPDIR}" && ls -R .
    fi
    return 1
  fi
  # Make binary executable for runner script
  chmod +x "${BINARY_PATH}"
  # Run the binary directly with provided arguments (already shifted)
  if [ $# -gt 0 ]; then
    log_info "Running ${BINARY_NAME} with $# argument(s)"
  else
    log_info "Running ${BINARY_NAME}"
  fi
  exec "${BINARY_PATH}" "$@"
}

# --- Configuration  ---
NAME='ghcp'
REPO='int128/ghcp'
EXT='.zip'

# use in logging routines
log_prefix() {
  echo "${REPO}"
}
# Set default log priority to warning for runner script (suppress info logs)
log_set_priority 3

parse_args "$@"
# Now shift the consumed arguments for runner script
shift "$PARSE_CONSUMED"

# --- Determine target platform ---
OS="${BINSTALLER_OS:-$(uname_os)}"
UNAME_OS="${OS}"

ARCH="${BINSTALLER_ARCH:-$(uname_arch)}"

log_info "Detected Platform: ${OS}/${ARCH}"

# --- Validate platform ---
uname_os_check "$OS"
uname_arch_check "$ARCH"

tag_to_version

resolve_asset_filename
# Pass remaining arguments to execute for runner script
execute "$@"
