#!/bin/bash
# =================
#
#
#
#
# legal_placeholder
#
#
#
# =================

set -e
OPTIONAL_BUNDLE_PATH=${OPTIONAL_BUNDLE_PATH:-""}
TARGET_REGISTRY_URL=${TARGET_REGISTRY_URL:-""}
OFFLINE_BUNDLE_PATH=${OFFLINE_BUNDLE_PATH:-""}
TMP_OFFLINE_FOLDER=""
SF_FOLDER_NAME="sf-images"
EXTRACT_FOLDER=${EXTRACT_FOLDER:-""}
BUNDLE_TYPE=""
PREPEND_TAG=""

function display_usage() {
  echo
  echo "***************************************************************************************"
  echo
  echo "hydrate-registry.sh hydrates a target OCI compliant registry from a downloaded images.tar bundle."
  echo
  echo "Usage:"
  echo "  $0 [flags]"
  echo
  echo "Parameters:"
  echo "  --target-registry-url                              Target OCI compliant registry for the artifacts."
  echo "  --offline-bundle-path                              Path to the offline bundle tar file."
  echo "  --optional-bundle-path                             Path to the optional bundle tar file."
  echo "  --extract-path                                     Location to extract the bundle."
  echo "  --bundle-type                                      Type of the bundle (ascmk or as, default is ascmk)."
  echo
  echo "Flags:"
  echo "  -h|--help                                         Display help"
  echo "  -d|--debug                                        Run in debug mode"
  echo
  echo "***************************************************************************************"
  echo
}

function parse_args() {
  while [ "$#" -gt 0 ]; do
    case "$1" in
      -d | --debug)
        echo "Running in debug"
        set -x
        shift
        ;;
      -h | --help)
        display_usage
        exit 0
        ;;
      --extract-path)
        if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
          EXTRACT_FOLDER="$2"
          shift 2
        else
          echo "Value for $1 is missing"
          exit 1
        fi
        ;;
      --offline-bundle-path)
        if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
          OFFLINE_BUNDLE_PATH="$2"
          shift 2
        else
          echo "Value for $1 is missing"
          exit 1
        fi
        ;;
      --optional-bundle-path)
        if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
          OPTIONAL_BUNDLE_PATH="$2"
          SF_FOLDER_NAME="sf-images"
          shift 2
        else
          echo "Value for $1 is missing"
          exit 1
        fi
        ;;
      --target-registry-url)
        if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
          TARGET_REGISTRY_URL="$2"
          shift 2
        else
          echo "Value for $1 is missing"
          exit 1
        fi
        ;;
      --bundle-type)
        if [ -n "$2" ] && [ "${2:0:1}" != "-" ]; then
          BUNDLE_TYPE=$(echo "$2" | tr '[:upper:]' '[:lower:]')
          if [ "$BUNDLE_TYPE" != "ascmk" ] && [ "$BUNDLE_TYPE" != "as" ]; then
            echo "Invalid value for --bundle-type. Expected 'ascmk' or 'as'."
            exit 1
          fi
          shift 2
        else
          echo "Value for $1 is missing"
          exit 1
        fi
        ;;
      *)
        echo "Invalid option: $1"
        exit 1
        ;;
    esac
  done

  if [ -z "$EXTRACT_FOLDER" ]; then
    echo "Mandatory option --extract-path is missing."
    display_usage
    exit 1
  fi

  # Check if mandatory options are provided
  if [ -z "$TARGET_REGISTRY_URL" ]; then
    echo "Mandatory option --target-registry-url is missing."
    display_usage
    exit 1
  fi

  if [ -n "$OFFLINE_BUNDLE_PATH" ] && [ -n "$OPTIONAL_BUNDLE_PATH" ]; then
    echo "Mandatory option --offline-bundle-path or --optional-bundle-path is missing. Only one should be provided."
    exit 1
  fi

  if [ -z "$OFFLINE_BUNDLE_PATH" ] && [ -z "$OPTIONAL_BUNDLE_PATH" ]; then
    echo "Mandatory option --offline-bundle-path or --optional-bundle-path is missing."
    exit 1
  fi

  if [ "$BUNDLE_TYPE" = "as" ]; then
    PREPEND_TAG="localhost:30071/"
  fi
}

function extract_bundle() {
  if [ ! -e "${EXTRACT_FOLDER}" ]; then
    echo "Path does not exist: ${EXTRACT_FOLDER}"
    exit 1
  fi
  echo "Importing bundle at ${OFFLINE_BUNDLE_PATH}"
  TMP_OFFLINE_FOLDER="$(mktemp -d -p "${EXTRACT_FOLDER}" -t offline-bundle.XXXXXXXXXX)"
  echo "Extracting ${OFFLINE_BUNDLE_PATH} to ${TMP_OFFLINE_FOLDER}"
  tar -xzf "${OFFLINE_BUNDLE_PATH}" -C "${TMP_OFFLINE_FOLDER}"
  echo "Files used for the offline bundle have been extracted to ${TMP_OFFLINE_FOLDER}"
}

function import_sf_images() {
  local dev_null="/dev/null"
  local image_inventory="${TMP_OFFLINE_FOLDER}/${SF_FOLDER_NAME}/image-tags.txt"
  local image_tar="${TMP_OFFLINE_FOLDER}/${SF_FOLDER_NAME}/images.tar"
  local lenghty_echo_message="This operation may be lengthy. Please allow for it to complete..."

  echo "Populating Docker Registry at https://${TARGET_REGISTRY_URL}"

  if [[ -f "${image_inventory}" ]]; then
    echo "Image inventory file $image_inventory found."
  else
    echo "Image inventory file $image_inventory not found."
    exit 1
  fi

  if [[ -f "${image_tar}" ]]; then
    echo "Image inventory file $image_tar found."
  else
    echo "Image inventory file $image_tar not found."
    exit 1
  fi

  local all_images_present=1

  while read -r image_name; do
    podman image exists "${TARGET_REGISTRY_URL}/${image_name}" || all_images_present=0
  done <"${image_inventory}"

  if ((all_images_present != 1)); then
    echo  "Loading image tar ${image_tar}"
    echo  "${lenghty_echo_message}"
    if ! podman load -i "$image_tar"; then
      echo "Image loading failed. Possible reasons: 1. Not enough disk space. 2. Image tar is corrupted."
      exit 1
    fi
    echo "Image loading succeeded."
  else
    echo  "All images present. Skipping podman load"
  fi
  while read -r image_name; do
    local try=0
    local maxtry=10
    local status="notready"
    while [[ ${status} == "notready" ]] && ((try != maxtry)); do
      try=$((try + 1))
      echo "Tagging image ${PREPEND_TAG}${image_name} -> ${TARGET_REGISTRY_URL}/${image_name}"
      if ! podman tag "${PREPEND_TAG}${image_name}" "${TARGET_REGISTRY_URL}/${image_name}"; then
        echo "Failed to tag image ${image_name}"
        exit 1
      fi
      echo  "Pushing image ${image_name}...try ${try}/${maxtry}" && sleep 5
      podman push "${TARGET_REGISTRY_URL}/${image_name}" \
        --tls-verify=false >>"${dev_null}" &&
        status="ready"
      [[ ${status} == "ready" ]] || sleep 60
    done
    if [[ ! ${status} == "ready" ]]; then
        echo "Failed to push image ${image_name}"
        exit 1
    fi
  done <"${image_inventory}"

  echo  "Populated Docker Registry"
}

function import_sf_charts() {
  local chart_inventory="${TMP_OFFLINE_FOLDER}/sf-helm/helm-tags.txt"

  echo "Populating Helm Registry at ${TARGET_REGISTRY_URL}"
  if [[ ! -f "${chart_inventory}" ]]; then
    echo "Chart inventory file ${chart_inventory} not found"
    exit 1
  fi
  while read -r line; do
    local chart_name file_name repo_url chart_namespace
    chart_name=$(awk '{print $1}' <<<"${line}")
    file_name=$(awk '{print $2}' <<<"${line}")
    local try=0
    local maxtry=10
    local status="notready"

    while [[ ${status} == "notready" ]] && ((try != maxtry)); do
      try=$((try + 1))
      chart_namespace=$(echo "${chart_name}" | cut -d "/" -f 1)
      repo_url="oci://${TARGET_REGISTRY_URL}/${chart_namespace}"
      echo "Pushing local chart ${TMP_OFFLINE_FOLDER}/sf-helm/${file_name} to ${repo_url}...try ${try}/${maxtry}"
      helm push "${TMP_OFFLINE_FOLDER}/sf-helm/${file_name}" "${repo_url}" && status="ready"
      [[ ${status} == "ready" ]] || sleep 2
    done

    if [[ ! ${status} == "ready" ]]; then
      echo "Failed to push chart ${chart_name} to ${repo_url}"
      exit 1
    fi
  done <"${chart_inventory}"

  echo "Populated Helm Registry"
}

function hydrate_from_bundle() {
  if [[ -z "${OPTIONAL_BUNDLE_PATH:-}" ]]; then
    import_sf_charts
  fi
  import_sf_images
}

function verify_podman_authentication() {
  if podman login "${TARGET_REGISTRY_URL}" --get-login &> /dev/null; then
    echo "Podman is logged in to ${TARGET_REGISTRY_URL}"
  else
    echo "Podman is not logged in. Please run 'podman login ${TARGET_REGISTRY_URL}' to log in."
    exit 1
  fi
}

function main() {
  verify_podman_authentication
  if [[ -n "${OPTIONAL_BUNDLE_PATH:-}" ]]; then
    OFFLINE_BUNDLE_PATH="${OPTIONAL_BUNDLE_PATH}"
  fi
  extract_bundle
  hydrate_from_bundle

  echo "Cleaning up temporary files"
  rm -rf "${TMP_OFFLINE_FOLDER:?}/"*
}

parse_args "$@"
main