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

# This script requires quicktype to be installed.
# While you can install it using npm, we have it in our devDependencies
# in ${PROJECT_ROOT}/package.json.
PROJECT_ROOT="$(git rev-parse --show-toplevel)"
if ! pnpm list | grep quicktype &>/dev/null; then
	echo "quicktype is required to run this script!"
	echo "Ensure that it is present in the devDependencies of ${PROJECT_ROOT}/package.json and then run pnpm install."
	exit 1
fi

DEST_FILENAME="dcspec_gen.go"
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
DEST_PATH="${SCRIPT_DIR}/${DEST_FILENAME}"

# Location of the JSON schema for the devcontainer specification.
SCHEMA_SRC="https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.base.schema.json"
SCHEMA_DEST="${SCRIPT_DIR}/devContainer.base.schema.json"

UPDATE_SCHEMA="${UPDATE_SCHEMA:-false}"
if [[ "${UPDATE_SCHEMA}" = true || ! -f "${SCHEMA_DEST}" ]]; then
	# Download the latest schema.
	echo "Updating schema..."
	curl --fail --silent --show-error --location --output "${SCHEMA_DEST}" "${SCHEMA_SRC}"
else
	echo "Using existing schema..."
fi

TMPDIR=$(mktemp -d)
trap 'rm -rfv "$TMPDIR"' EXIT

show_stderr=1
exec 3>&2
if [[ " $* " == *" --quiet "* ]] || [[ ${DCSPEC_QUIET:-false} == "true" ]]; then
	# Redirect stderr to log because quicktype can't infer all types and
	# we don't care right now.
	show_stderr=0
	exec 2>"${TMPDIR}/stderr.log"
fi

if ! pnpm exec quicktype \
	--src-lang schema \
	--lang go \
	--top-level "DevContainer" \
	--out "${TMPDIR}/${DEST_FILENAME}" \
	--package "dcspec" \
	"${SCHEMA_DEST}"; then
	echo "quicktype failed to generate Go code." >&3
	if [[ "${show_stderr}" -eq 1 ]]; then
		cat "${TMPDIR}/stderr.log" >&3
	fi
	exit 1
fi

if [[ "${show_stderr}" -eq 0 ]]; then
	# Restore stderr.
	exec 2>&3
fi
exec 3>&-

# Format the generated code.
go run mvdan.cc/gofumpt@v0.8.0 -w -l "${TMPDIR}/${DEST_FILENAME}"

# Add a header so that Go recognizes this as a generated file.
if grep -q -- "\[-i extension\]" < <(sed -h 2>&1); then
	# darwin sed
	sed -i '' '1s/^/\/\/ Code generated by dcspec\/gen.sh. DO NOT EDIT.\n\/\/\n/' "${TMPDIR}/${DEST_FILENAME}"
else
	sed -i'' '1s/^/\/\/ Code generated by dcspec\/gen.sh. DO NOT EDIT.\n\/\/\n/' "${TMPDIR}/${DEST_FILENAME}"
fi

mv -v "${TMPDIR}/${DEST_FILENAME}" "${DEST_PATH}"
