#!/bin/bash
set -euo pipefail

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
ROOT_DIR=$(cd "${SCRIPT_DIR}/.." && pwd)

MAKESELF_VERSION="2.5.0"
MAKESELF_REPO="cann-src-third-party/makeself"
MAKESELF_BRANCH="master"
MAKESELF_DIR="${ROOT_DIR}/makeself"
MAKESELF_SCRIPT="${MAKESELF_DIR}/makeself.sh"
MAKESELF_HEADER="${MAKESELF_DIR}/makeself-header.sh"
MAKESELF_TAR="makeself-release-${MAKESELF_VERSION}.tar.gz"
MAKESELF_PATCH="makeself-${MAKESELF_VERSION}.patch"
MAKESELF_API_BASE="https://gitcode.com/api/v5/repos/${MAKESELF_REPO}/contents"

# Must be a global variable: EXIT trap runs after main() returns.
patch_file=""

fetch_download_url() {
    local file="$1"
    local url=""

    url=$(python3 - "$file" <<'PY'
import json
import sys
import urllib.request

file_name = sys.argv[1]
api_url = (
    f"https://gitcode.com/api/v5/repos/cann-src-third-party/makeself/contents/"
    f"{file_name}?ref=master"
)
try:
    with urllib.request.urlopen(api_url) as resp:
        data = json.load(resp)
    download_url = data.get("download_url", "")
    if not download_url:
        raise ValueError("download_url is empty")
    print(download_url)
except Exception as exc:
    print(f"ERROR: failed to resolve download URL for {file_name}: {exc}", file=sys.stderr)
    sys.exit(1)
PY
)

    if [[ -z "${url}" ]]; then
        echo "ERROR: empty download URL for ${file}" >&2
        exit 1
    fi
    printf '%s' "${url}"
}

check_dependency() {
    if ! command -v curl &> /dev/null; then
        echo "ERROR: please install curl first"
        exit 1
    fi
    if ! command -v python3 &> /dev/null; then
        echo "ERROR: please install python3 first"
        exit 1
    fi
    if ! command -v patch &> /dev/null; then
        echo "ERROR: please install patch first"
        exit 1
    fi
}

FIXED_GREP_PATTERN="grep -o -E -e '--[^ ]+'"
SCRIPT_ARGS_CHECK_WARN='log "WARNING" "Unknown argument:'

is_makeself_ready() {
    [ -d "${MAKESELF_DIR}" ] && \
    [ -f "${MAKESELF_SCRIPT}" ] && \
    [ -x "${MAKESELF_SCRIPT}" ] && \
    [ -f "${MAKESELF_HEADER}" ] && \
    grep -q 'Script_Args_Check' "${MAKESELF_HEADER}" && \
    grep -qF "${FIXED_GREP_PATTERN}" "${MAKESELF_HEADER}" && \
    grep -qF "${SCRIPT_ARGS_CHECK_WARN}" "${MAKESELF_HEADER}"
}

needs_grep_fixup() {
    [ -f "${MAKESELF_HEADER}" ] || return 1
    grep -q 'Script_Args_Check' "${MAKESELF_HEADER}" || return 1
    grep -qF "${FIXED_GREP_PATTERN}" "${MAKESELF_HEADER}" && return 1
    return 0
}

needs_script_args_check_fixup() {
    [ -f "${MAKESELF_HEADER}" ] || return 1
    grep -q 'Script_Args_Check' "${MAKESELF_HEADER}" || return 1
    grep -qF "${SCRIPT_ARGS_CHECK_WARN}" "${MAKESELF_HEADER}" && return 1
    return 0
}

fix_makeself_header() {
    python3 - "${MAKESELF_HEADER}" "${FIXED_GREP_PATTERN}" <<'PY'
import re
import sys
from pathlib import Path

header_path = Path(sys.argv[1])
fixed_grep = sys.argv[2]
content = header_path.read_text()

patterns = [
    'grep -o -E "\\-\\-[^ ]+"',
    'grep -o -E "--[^ ]+"',
]
updated = content
for pattern in patterns:
    updated = updated.replace(pattern, fixed_grep)

if updated == content:
    updated = re.sub(
        r'grep -o -E "\-\-\[\^ \]\+"',
        fixed_grep,
        content,
        count=1,
    )

if fixed_grep not in updated:
    print("ERROR: failed to fix grep pattern in makeself-header.sh", file=sys.stderr)
    sys.exit(1)

needle = "\t--quiet)\n\tquiet=y\n\tshift\n\t;;"
if "\t-q)\n" not in updated and needle in updated:
    updated = updated.replace(
        needle,
        "\t-q)\n\tquiet=y\n\tshift\n\t;;\n" + needle,
        1,
    )

script_args_check_exit = """    MS_Help
    exit 1
}"""
script_args_check_warn = """    log "WARNING" "Unknown argument: $1"
    return
}"""
if script_args_check_exit in updated:
    updated = updated.replace(script_args_check_exit, script_args_check_warn, 1)

header_path.write_text(updated)
PY
}

cleanup_patch_file() {
    if [[ -n "${patch_file}" ]]; then
        rm -f "${patch_file}"
        patch_file=""
    fi
}

main() {
    if is_makeself_ready; then
        echo "makeself is ready: ${MAKESELF_DIR}"
        exit 0
    fi

    if needs_grep_fixup || needs_script_args_check_fixup; then
        echo "Fixing makeself header..."
        fix_makeself_header
        chmod +x "${MAKESELF_SCRIPT}"
        if is_makeself_ready; then
            echo "makeself is ready: ${MAKESELF_DIR}"
            exit 0
        fi
    fi

    echo "makeself is missing, incomplete, or not patched, preparing..."
    rm -rf "${MAKESELF_DIR}"
    mkdir -p "${MAKESELF_DIR}"

    local tar_url patch_url
    tar_url=$(fetch_download_url "${MAKESELF_TAR}")
    patch_url=$(fetch_download_url "${MAKESELF_PATCH}")

    echo "Downloading ${MAKESELF_TAR} from GitCode..."
    curl -sSL --retry 3 --fail "${tar_url}" \
        | tar -xz -C "${MAKESELF_DIR}" --strip-components=1

    patch_file=$(mktemp)
    if [[ -z "${patch_file}" || ! -f "${patch_file}" ]]; then
        echo "ERROR: failed to create temporary patch file" >&2
        exit 1
    fi
    trap cleanup_patch_file EXIT

    echo "Downloading ${MAKESELF_PATCH} from GitCode..."
    curl -sSL --retry 3 --fail "${patch_url}" -o "${patch_file}"

    echo "Applying ${MAKESELF_PATCH}..."
    patch -d "${MAKESELF_DIR}" -p1 --forward < "${patch_file}"

    echo "Fixing makeself header quirks..."
    fix_makeself_header

    chmod +x "${MAKESELF_SCRIPT}"

    if ! is_makeself_ready; then
        echo "ERROR: failed to prepare patched makeself" >&2
        echo "  Script_Args_Check: $(grep -c 'Script_Args_Check' "${MAKESELF_HEADER}" || true)" >&2
        echo "  fixed grep pattern: $(grep -cF "${FIXED_GREP_PATTERN}" "${MAKESELF_HEADER}" || true)" >&2
        echo "  script args check warn: $(grep -cF "${SCRIPT_ARGS_CHECK_WARN}" "${MAKESELF_HEADER}" || true)" >&2
        exit 1
    fi

    echo "makeself preparation completed: ${MAKESELF_DIR}"
    trap - EXIT
    cleanup_patch_file
}

check_dependency
main