#!/usr/bin/env bash

# SPDX-FileCopyrightText: the secureCodeBox authors
#
# SPDX-License-Identifier: Apache-2.0

set -euo pipefail

COLOR_PREFIX="\e[32m"
COLOR_ERROR="\e[31m"
COLOR_RESET="\e[0m"

#
# This script generates various HElm documentation from chart files
#
# This script was extracted from the main Makefile to make both easier maintainable.
#
# This script provides some switches to generate particular parts of the whole documentation. The documentation
# Consists of three parts:
#
# 1. A main README file for the Chart. This is generated by the switch `--readme`. This is exceptional from the other
#    switches because it expects thebase directory with all chart files in sub directories. All the readmes for all
#    charts will be generated in one sigle run.
# 2. Chart documentation for ArtifactHub. This file is generated as part of this script when invoked with any switch
#    except the`--readme` switch (see above). Not for all images (see below) a chart documentation wil be generated!
# 3. Image documentation forDockerHub. . This file is generated as part of this script when invoked with any switch
#    except the`--readme` switch (see above). Not for all charts (see below) a DockerHub documentation will be generated!

USAGE="$(basename "${0}") --scanner|--hook|--demo-target|--operator|--auto-discovery|--readme path/to/Chart.yaml|dir/with/charts path/to/.helm-docs"

DOC_TYPE="${1:-}"
# This is either path to a Chart.yml or a directory containing some of them.
CHART_FILE_OR_DIR="${2:-}"
HELM_DOCS_DIR="${3:-}"

DOCS_DIR_NAME="docs"

function log() {
  echo -e "${COLOR_PREFIX}SCB${COLOR_RESET} ${1}"
}

function error() {
  log >&2 "${COLOR_ERROR}ERROR${COLOR_RESET}: ${1}"
}

function validate_args() {
  if [[ -z "${DOC_TYPE}" ]]; then
    error "No doc type  given as first argument!"
    error "${USAGE}"
    exit 1
  fi

  if [[ -z "${CHART_FILE_OR_DIR}" ]]; then
    error "No chart file given as second argument!"
    error "${USAGE}"
    exit 1
  fi

  if [[ -z "${HELM_DOCS_DIR}" ]]; then
    error "No helm docs dir given as third argument!"
    error "${USAGE}"
    exit 1
  fi
}

function generate_docs() {
  local chart_search_root output_file base_template local_template output_template

  chart_search_root="${1}"
  output_file="${2}"

  base_template="${HELM_DOCS_DIR}/templates.gotmpl"
  local_template=".helm-docs.gotmpl"
  # Strip of the docs dir prefix from output file.
  output_template="${HELM_DOCS_DIR}/${output_file#"$DOCS_DIR_NAME/"}.gotmpl"

  helm-docs \
    --chart-search-root="${chart_search_root}" \
    --output-file="${output_file}" \
    --template-files="${base_template}" \
    --template-files="${local_template}" \
    --template-files="${output_template}"
}

function generate_scanner_docs() {
  local scanner_dir parser_dir scanner_image_dir

  scanner_dir="${1}"
  parser_dir="${scanner_dir}/parser"
  scanner_image_dir="${scanner_dir}/scanner"

  if [ -d "${parser_dir}" ]; then
    log "Parser found at: '${parser_dir}'. Generating parser doc..."
    # Since parsers do not have an own Helm chart, but are included in
    # the Helm chart of the related scanner, we do not generate a doc file
    # for ArtifactHub.
    generate_docs "${scanner_dir}" "${DOCS_DIR_NAME}/README.DockerHub-Parser.md"
  else
    log "No parser found '${parser_dir}'! Skipping parser doc."
  fi

  if [ -d "${scanner_image_dir}" ]; then
    log "Scanner found at: '${scanner_image_dir}'. Generating scanner doc..."
    # For own custom scanners (e.g. Nmap which does not provide an official image)
    # we generate docs for DockerHub, but not for ArtifactHub because the scanner
    # image does not have its own Helm chart. It belongs to the main chart which
    # is generated separately.
    generate_docs "${scanner_dir}" "${DOCS_DIR_NAME}/README.DockerHub-Scanner.md"
  else
    log "No scanner found at '${scanner_image_dir}'! Skipping scanner doc."
  fi

  log "Generating main doc..."
  # Here we generate the main doc of the Helm chart for artifact hub.`
  generate_docs "${scanner_dir}" "${DOCS_DIR_NAME}/README.ArtifactHub.md"
}

function generate_hook_docs() {
  local hook_dir

  hook_dir="${1}"
  generate_docs "${hook_dir}" "${DOCS_DIR_NAME}/README.DockerHub-Hook.md"
  generate_docs "${hook_dir}" "${DOCS_DIR_NAME}/README.ArtifactHub.md"
}

function generate_demo_target_docs() {
  local demo_target_dir

  demo_target_dir="${1}"
  generate_docs "${demo_target_dir}" "${DOCS_DIR_NAME}/README.DockerHub-Target.md"
  generate_docs "${demo_target_dir}" "${DOCS_DIR_NAME}/README.ArtifactHub.md"
}

function generate_operator_docs() {
  local operator_dir

  operator_dir="${1}"
  generate_docs "${operator_dir}" "${DOCS_DIR_NAME}/README.DockerHub-Core.md"
  generate_docs "${operator_dir}" "${DOCS_DIR_NAME}/README.ArtifactHub.md"
}

function generate_auto_discovery_docs() {
  local auto_discovery_dir

  auto_discovery_dir="${1}"
  generate_docs "${auto_discovery_dir}" "${DOCS_DIR_NAME}/README.DockerHub-Core.md"
  generate_docs "${auto_discovery_dir}" "${DOCS_DIR_NAME}/README.ArtifactHub.md"
}

function generate_readme() {
  local repo_base_dir

  repo_base_dir="${1}"

  generate_docs "${repo_base_dir}" "README.md"
}

function main() {
  validate_args

  log "Generating docs for ${CHART_FILE_OR_DIR}..."

  local work_dir docs_dir

  # There are two main cases this script is invoked:
  # 1. For one found chart file (e.g. of a scanner or hook): In this case we need
  #    the parent directory of this chart file as working directory and we ned to ensure
  #    that there is a ${DOCS_DIR_NAME} directory where we store the generated files.
  # 2. For generating the top level READMEs. Here we expect a base directory as working dir
  #    from where helm-docs collect all Chart.yml by itself.
  if [[ -d "${CHART_FILE_OR_DIR}" ]]; then
    work_dir="${CHART_FILE_OR_DIR}"
  else
    work_dir="$(dirname "${CHART_FILE_OR_DIR}")"
    docs_dir="${work_dir}/${DOCS_DIR_NAME}"

    if [ ! -d "${docs_dir}" ]; then
      log "Ignoring docs creation process for '${CHART_FILE_OR_DIR}' because docs folder found at: '${docs_dir}'!"
      exit 0
    fi
  fi

  case "${DOC_TYPE}" in
  "--scanner")
    generate_scanner_docs "${work_dir}"
    ;;
  "--hook")
    generate_hook_docs "${work_dir}"
    ;;
  "--demo-target")
    generate_demo_target_docs "${work_dir}"
    ;;
  "--operator")
    generate_operator_docs "${work_dir}"
    ;;
  "--auto-discovery")
    generate_auto_discovery_docs "${work_dir}"
    ;;
  "--readme")
    generate_readme "${work_dir}"
    ;;
  *)
    error "Unsupported doc type: ${DOC_TYPE}!"
    error "${USAGE}"
    ;;
  esac
}

main
