#!/usr/bin/env bash

# Copyright 2022 The cert-manager Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# This script constructs a 'content/' directory that contains content for all
# configured versions of the documentation which use the "github.com/jetstack/cert-manager" import path

set -o errexit
set -o nounset
set -o pipefail

REPO_ROOT="${REPO_ROOT:-$(cd "$(dirname "$0")/../.." && pwd)}"

if ! command -v go &>/dev/null; then
  echo "Ensure go is installed"
  exit 1
fi

if ! command -v npm &>/dev/null; then
  echo "Ensure npm is installed"
  exit 1
fi

tmpdir="$(mktemp -d)"
apidocstmpdir="$(mktemp -d)"

cleanup() {
  rm -rf "${apidocstmpdir}"
  rm -rf "${tmpdir}"
}
trap cleanup EXIT

# Create fake GOPATH
echo "+++ Creating temporary GOPATH"
export GOPATH="${tmpdir}/go"
export GO111MODULE="on"
GOROOT="$(go env GOROOT)"
export GOROOT
GOBIN="${tmpdir}/bin"
export GOBIN

go install github.com/ahmetb/gen-crd-api-reference-docs@v0.3.0

# genversion takes two arguments (branch in cert-manager repo and a directory in
# this repo under content) and generates API reference docs from cert-manager
# branch for the path in this repo.
genversion() {
  checkout "$1"
  gendocs "$2"
}

genversionwithcli() {
  genversion "$1" "$2"

  genclireference "$2" "cmd/acmesolver" "acmesolver"
  genclireference "$2" "cmd/cainjector" "cainjector"
  genclireference "$2" "cmd/ctl" "cmctl"
  genclireference "$2" "cmd/controller" "controller"
  genclireference "$2" "cmd/webhook" "webhook"

  # if any of the above steps succeeded copy over the index file
  if [ "$2" != "docs" ] && [ -d "$REPO_ROOT/content/$2/cli" ]; then
    cp "$REPO_ROOT/content/docs/cli/README.md" "${REPO_ROOT}/content/$2/cli/"
  fi
}

checkout() {
  branch="$1"

  mkdir -p "${GOPATH}/src/github.com/jetstack"
  gitdir="${GOPATH}/src/github.com/jetstack/cert-manager"
  echo "+++ Cloning cert-manager repository..."
  git clone "https://github.com/jetstack/cert-manager.git" "$gitdir" --depth 1 --branch "$branch"
  pushd "$gitdir"
  echo "+++ Running 'go mod vendor' (this may take a while)"
  go mod vendor
}

gendocs() {
  outputdir="$1"
  mkdir -p "${apidocstmpdir}/${outputdir}"/
  echo "+++ Generating reference docs..."
  "${GOBIN}/gen-crd-api-reference-docs" \
    -config "${REPO_ROOT}/scripts/gendocs/config.json" \
    -template-dir "${REPO_ROOT}/scripts/gendocs/templates" \
    -api-dir "./pkg/apis" \
    -out-file "${apidocstmpdir}/${outputdir}"/api-docs.md

  "${REPO_ROOT}"/scripts/gendocs/postprocess/api-doc-postprocess.js <"${apidocstmpdir}/${outputdir}/api-docs.md" >"${REPO_ROOT}/content/${outputdir}/reference/api-docs.md"

  rm -rf vendor/
  popd
}

# genclireference will attempt to run main.go --help for the target and write the output to a markdown file
genclireference() {
  if [ ! -f "$2/main.go" ]; then
    echo "+++ target $2 does not exist, skipping..."
    return
  fi

  # hacky way to figure out if the target has the correct structure
  # differs between older version but this catches the corner cases
  if [[ ! -d "$2/app" ]] && [ ! -d "$2/cmd" ]; then
    echo "+++ app directory for $2 does not exist, skipping..."
    return
  fi

  # combined with the check above we can handle all versions
  # for example release-0.15 webhook has the correct directory structure but does not use cobra
  if ! grep -q "@com_github_spf13_cobra//:go_default_library" "$2/app/BUILD.bazel" && ! grep -q "@com_github_spf13_cobra//:go_default_library" "$2/cmd/BUILD.bazel"; then
    return
  fi

  outputdir="$1"
  target="$2"
  name="$3"
  echo "+++ Generating CLI reference docs for $target ..."

  mkdir -p "${REPO_ROOT}/content/${outputdir}/cli/"

  output=$(go run "$target/main.go" --help)
  cat >"${REPO_ROOT}/content/${outputdir}/cli/$name.md" <<EOF
---
title: $name CLI reference
description: "cert-manager $name CLI documentation"
---
\`\`\`
$output
\`\`\`
EOF
}

# The branches named here exist in the `cert-manager/cert-manager` repo.

# Note that we cannot generate docs for any version after 1.7 using this script!
# In 1.8 we changed the import path, and gen-crd-api-reference-docs doesn't seem module-aware
# This script is _only_ for generating docs for versions of cert-manager with the
# github.com/jetstack/cert-manager import path!

###############################################################################
# The commands below can be used to re-generate
# documentation for older versions.
#
# If you backport a change to flags or API specs you must uncomment
# the relevant section(s) below for affected version(s) and run this script.
#
# It will generate the necessary documentation and you can add
# it to the git index.
#
# Afterwards you should put the commands behind a comment to avoid
# slowing down builds in CI.
###############################################################################

# Special handling for release-1.6 because the legacy APIs were still present in
# the CRDs and in public `pkg/` directory but we do not want to generate API
# docs for those legacy API versions.

# In cert-manager 1.6 cert-manager.io and acme.cert-manager.io alpha and beta
# API versions are no longer served, but the apis are still in the codebase. We
# don't want to show the docs for those API versions so this is a workaround.
# This will only be necessary for the release-1.6 branch.

generate_release16() {
  # The special-case for release-1.6 is in a function to make it easier to
  # comment and uncomment below
  checkout "release-1.6"
  # Generate CLI reference docs before deleting the legacy API,
  # as they will not compile otherwise
  genclireference "v1.6-docs" "cmd/acmesolver" "acmesolver"
  genclireference "v1.6-docs" "cmd/cainjector" "cainjector"
  genclireference "v1.6-docs" "cmd/ctl" "cmctl"
  genclireference "v1.6-docs" "cmd/controller" "controller"
  genclireference "v1.6-docs" "cmd/webhook" "webhook"

  rm -r pkg/apis/acme/v1alpha2
  rm -r pkg/apis/acme/v1alpha3
  rm -r pkg/apis/acme/v1beta1
  rm -r pkg/apis/certmanager/v1alpha2
  rm -r pkg/apis/certmanager/v1alpha3
  rm -r pkg/apis/certmanager/v1beta1

  gendocs "v1.6-docs"
}

###### WARNING ######
# If you uncomment any of the below lines,
# you'll also need to uncomment "${REPO_ROOT}/scripts/gendocs/generate-old-import-path-docs" in "scripts/gendocs/generate"
# for any of the below to matter!
###### WARNING ######

#genversionwithcli "release-1.7" "v1.7-docs"
#generate_release16
#genversionwithcli "release-1.5" "v1.5-docs"
#genversionwithcli "release-1.4" "v1.4-docs"
#genversionwithcli "release-1.3" "v1.3-docs"
#genversionwithcli "release-1.2" "v1.2-docs"
#genversionwithcli "release-1.1" "v1.1-docs"
#genversionwithcli "release-1.0" "v1.0-docs"

# echo "Generated reference documentation for cert-manager versions with an old github.com/jetstack/cert-manager import path"
