#!/bin/bash

set -e

# Parse arguments
spec_path=''
output_path=''
generator=''
generator_dir=''
additional_properties=''
openapi_normalizer=''
src_dir='src'
tst_dir='test'
extra_vendor_extensions=''
generate_alias_as_model=''
while [[ "$#" -gt 0 ]]; do case $1 in
  --spec-path) spec_path="$2"; shift;;
  --output-path) output_path="$2"; shift;;
  --generator) generator="$2"; shift;;
  --generator-dir) generator_dir="$2"; shift;;
  --additional-properties) additional_properties="$2"; shift;;
  --openapi-normalizer) openapi_normalizer="$2"; shift;;
  --src-dir) src_dir="$2"; shift;;
  --tst-dir) tst_dir="$2"; shift;;
  --extra-vendor-extensions) extra_vendor_extensions="$2"; shift;;
  --generate-alias-as-model) generate_alias_as_model='true'; ;;
esac; shift; done

echo "Generating OpenAPI $generator_dir ($generator)..."
working_dir=$(pwd)

# Get the directory this script is executing in (scripts/generators)
script_dir="$( cd -- "$(dirname $([ -L "${BASH_SOURCE[0]:-$0}" ] && readlink -f "${BASH_SOURCE[0]:-$0}" || echo "${BASH_SOURCE[0]:-$0}"))" >/dev/null 2>&1 ; pwd -P )";

# load common package manager helper functions
. "$script_dir/../common/common.sh"

# Create a temporary directory
tmp_dir=$(mktemp -d "${TMPDIR:-/tmp/}generate-client-$generator_dir.XXXXXXXXX")
cd $tmp_dir

log "generate :: tmp_dir :: $tmp_dir"

# Copy the specific generator directory into the temp directory
cp -r $script_dir/$generator_dir/* .

# Install dependencies
install_packages

# Pre-process the spec to add any extra vendor extensions used for code generation only.
# This allows for custom parameters to be passed to the code generation templates
log "preprocess spec :: $spec_path"
processed_spec_path="$tmp_dir/.preprocessed-api.json"
cp $script_dir/pre-process-spec.ts .
run_command ts-node pre-process-spec.ts \
  --specPath="$working_dir/$spec_path" \
  --outputSpecPath="$processed_spec_path" \
  --extraVendorExtensions="$extra_vendor_extensions"

# Support special placeholders of {{src}} and {{tst}} in config.yaml to ensure our custom templates get written to the correct folder
sed 's|{{src}}|'"$src_dir"'|g' config.yaml > config.tmp.yaml
sed 's|{{tst}}|'"$tst_dir"'|g' config.tmp.yaml > config.final.yaml

# Copy the openapitools.json config into the working directory so it's honoured by the generator cli
cp $working_dir/$output_path/openapitools.json .

# Workaround for code generation with JDK 11+
# See: https://github.com/OpenAPITools/openapi-generator/issues/13684
export JAVA_OPTS="--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED"

openapi_generate() {
  run_command openapi-generator-cli generate \
    --log-to-stderr \
    --generator-name $generator \
    --skip-operation-example \
    ${generate_alias_as_model:+"--generate-alias-as-model"} \
    --minimal-update \
    --template-dir templates \
    --config config.final.yaml \
    --additional-properties="$additional_properties" \
    ${openapi_normalizer:+"--openapi-normalizer=$openapi_normalizer"} \
    --input-spec "$processed_spec_path" \
    --output "$working_dir/$output_path" $@
}

# Generate the client
openapi_generate

# If a .open-api-generator-ignore-handlebars ignore file exists, we run a second pass with the handlebars template engine
handlebars_ignore_file="$working_dir/$output_path/.openapi-generator-ignore-handlebars"
if [ -f "$handlebars_ignore_file" ]; then
  # Save the files metadata file from our first pass
  generated_files_metadata_file="$working_dir/$output_path/.openapi-generator/FILES"
  if [ -f "$generated_files_metadata_file" ]; then
    cp $generated_files_metadata_file ./first-pass-files
  fi

  # Generate again, using the handlebars engine
  openapi_generate \
    --engine handlebars \
    --ignore-file-override "$handlebars_ignore_file"

  # Write the first pass generated files to the files metadata file, so it includes what was generated in both passes
  if [ -f "$generated_files_metadata_file" ]; then
    cat ./first-pass-files >> $generated_files_metadata_file
  fi
fi

# Post processing
cp $script_dir/post-process.ts .
run_command ts-node post-process.ts \
  --outputPath="$working_dir/$output_path"

# Clean up empty directories left over by openapi generator
log "Cleaning up empty directories"
find "$working_dir/$output_path" -type d -empty -print -delete

echo "$generator_dir ($generator) OpenAPI generation done!"

# Clean up
cd $working_dir
rm -rf $tmp_dir
