#!/bin/bash

set -e
set -o pipefail

GIT=${GIT:="git"}

repoRoot="$("$GIT" rev-parse --show-toplevel)"/libs/ocppi
cd "$repoRoot/tools/codegen"

git submodule update --init --depth 1

QUICKTYPE=${QUICKTYPE:=""}

if [ -z "$QUICKTYPE" ]; then
	pushd quicktype
	npm i
	npm run build
	popd
fi

quicktype() {
	if [ -z "$QUICKTYPE" ]; then
		pushd quicktype
		npx quicktype "$@"
		popd
	else
		exec $QUICKTYPE "$@"

	fi
}

generate() {
	schema="$1"
	shift
	toplevel_type="$1"
	shift
	namespace="$1"
	shift
	include="$1"
	shift
	output_path="$1"

	if [[ ! -f "$schema" ]]; then
		echo "$schema not found" || exit 255
	fi

	filename="/dev/null"

	while read -r line; do
		if [[ $line != //\ stdout &&
			$line != //*.hpp &&
			$line != \#include\ \"*\" ]]; then
			echo "$line" >>"$filename"
			continue
		fi

		if [[ $line == \#include\ \"*\" ]]; then
			header=${line#\#include\ \"}
			header=${header%\"}
			printf "#include \"%s/%s\"\n" \
				"$output_path" \
				"$header" \
				>>"$filename"
			continue
		fi

		echo "// clang-format on" >>"$filename"

		filename="${repoRoot}/$include/$output_path/${line#\/\/ }"
		if [[ $line == //\ stdout ]]; then
			filename="/dev/null"
		fi

		# echo "generating $filename"

		mkdir -p "$(dirname "$filename")"
		{
			echo "// Thish file is generated by /tools/codegen"
			echo "// DO NOT EDIT IT."
			echo ""
			echo "// clang-format off"
		} >"$filename"
	done < <(quicktype "$schema" \
		--lang c++ \
		-s schema \
		-t "$toplevel_type" \
		--namespace "$namespace" \
		--code-format with-struct \
		--source-style multi-source \
		--include-location global-include \
		--type-style pascal-case-upper-acronyms \
		--member-style camel-case-upper-acronyms \
		--enumerator-style pascal-case-upper-acronyms \
		--no-boost \
		--hide-null-optional)

	{
		echo ""
		echo "// clang-format on"
	} >>"$filename"
}

# Generate types from OCI runtime specification.

generate \
	"$repoRoot/runtime-spec/schema/config-schema.json" \
	Config \
	"ocppi::runtime::config::types" \
	"include" \
	"ocppi/runtime/config/types"

generate \
	"$repoRoot/runtime-spec/schema/state-schema.json" \
	State \
	"ocppi::runtime::state::types" \
	"include" \
	"ocppi/runtime/state/types"

generate \
	"$repoRoot/runtime-spec/schema/features-schema.json" \
	Features \
	"ocppi::runtime::features::types" \
	"include" \
	"ocppi/runtime/features/types"

# Generate types from ocppi API json schemas.

generate \
	"$repoRoot/api/schema/ocppi-types-schema.json" \
	types \
	"ocppi::types" \
	"include" \
	"ocppi/types"

PATCH_FILE=${PATCH_FILE:="$repoRoot"/tools/codegen/fix.patch}
if [[ ! -f "$PATCH_FILE" ]]; then
	echo "No patch file found at $PATCH_FILE"
	exit
fi

pushd "$repoRoot"
cp -r "$repoRoot/$include" "$repoRoot/$include.orig"
patch -s -p0 <"$PATCH_FILE"
rm -r "$repoRoot/$include.orig"
popd