#!/usr/bin/env bash

set -e

function get_host_from_ref() {
  echo "$(echo ${FULL_IDENTIFIER} | awk '{if(split($0, parts, "/")==3) {print(parts[1])} else {print("registry.hub.docker.com")}}')"
}

function get_org_from_ref() {
  echo "$(echo ${FULL_IDENTIFIER} | awk '{if(split($0, parts, "/")==3) {print(parts[2])} else {print(parts[1])}}')"
}

function get_repo_and_tag_from_ref() {
  echo "$(echo ${FULL_IDENTIFIER} | awk '{if(split($0, parts, "/")==3) {print(parts[3])} else {print(parts[2])}}')"
}

function get_repo_from_ref() {
  local repo_and_tag
  repo_and_tag=$(get_repo_and_tag_from_ref)
  echo "$(echo ${repo_and_tag} | awk -F':' '{print $1}')"
}

function get_tag_from_ref() {
  local repo_and_tag
  repo_and_tag=$(get_repo_and_tag_from_ref)
  echo "$(echo ${repo_and_tag} | awk -F':' '{print $2}')"
}

# Check whether the reference exists on the registry
function tag_exists() {
  local registry_host
  local org_name
  local repo
  local tag
  registry_host=$(get_host_from_ref)
  if [[ ${registry_host} == docker\.io ]]; then
    registry_host="registry.hub.docker.com"
  fi
  org_name=$(get_org_from_ref)
  repo=$(get_repo_from_ref)
  tag=$(get_tag_from_ref)
  response=$(curl -Iso /dev/null -w "%{http_code}" "https://${registry_host}/v2/namespaces/${org_name}/repositories/${repo}/tags/${tag}")
  if [[ "${response}" =~ 2[[:digit:]]{2} ]]; then
    echo "true"
  else
    echo "false"
  fi
}

# Tests for a release tag version, optionally including minor and patch numbers
# amd64-0.3.20250101001122
# amd64-0.3-rolling-daily
# arm64-0.3
# amd64-0
function is_release_version() {
  local tag
  tag=$(get_tag_from_ref)
  if [[ ${tag} =~ ^(amd64|arm64)-[0-9]+(\.[0-9]+(\.[0-9]{14}|-rolling-daily)?)?$ ]]; then
    echo "true"
  else
    echo "false"
  fi
}

# Get the latest stable tag for the provided release identifier
# Only considers stable versions like 'amd64-0.3.20250101001122'
# Ignores floating versions like 'amd64-develop', 'arm64-0.3'
function get_latest_stable_tag() {
  local registry_host
  local org_name
  local repo
  local tag
  registry_host=$(get_host_from_ref)
  if [[ ${registry_host} == docker\.io ]]; then
    registry_host="registry.hub.docker.com"
  fi
  org_name=$(get_org_from_ref)
  repo=$(get_repo_from_ref)
  tag=$(get_tag_from_ref)
  local plugin_version_regex=
  if [[ ${tag} =~ ^(amd64|arm64)(-([0-9]+(\.[0-9]+)*))? ]]; then
    local plugin_arch="${BASH_REMATCH[1]}"
    local plugin_version="${BASH_REMATCH[3]}"
    if [[ -z ${plugin_version} ]]; then
      >&2 echo "Provided plugin version does not use a recognized number. Will find latest stable release for architecture."
      plugin_version_regex='^'${plugin_arch}'-[0-9]+\.[0-9]+'
    else
      plugin_version_regex='^'${plugin_arch}-$(echo ${plugin_version} | \
        awk '{ num_parts=split($0, parts, "."); \
          if (num_parts >=3) { print parts[1] "." parts[2] } \
          else if (num_parts == 1) { print parts[1] ".[0-9]+" } \
          else { print $0 }}' | \
        sed -r 's/\./\\\./g')
    fi
    plugin_version_regex="${plugin_version_regex}"'\.[0-9]{14}$'
  else
    >&2 echo "Error: Plugin tag is expected to start with \"amd64\" or \"arm64\""
    exit 1
  fi

  local url_base="https://${registry_host}/v2/namespaces/${org_name}/repositories/${repo}/tags"
  local page=1
  local latest_version
  local tag_page
  local found_version
  while [[ -n ${page} ]]; do
    tag_page=$(curl -s "${url_base}?page=${page}&page_size=100")
    if [[ $(echo "${tag_page}" | ${YQ} '.next != null' ) == true ]]; then
      ((page++))
    else
      unset page
    fi
    found_version=$(echo "${tag_page}" | ${YQ} -r '.results[].name' | grep -E ${plugin_version_regex} | sort -V | tail -n 1)
    if [[ ${found_version} > ${latest_version} ]]; then
      latest_version=${found_version}
    fi
  done

  echo "${latest_version}"
}

function display_help() {
echo -e "Usage:\t$0 PLUGIN_IDENTIFIER OPTION"
echo -e "\tPLUGIN_IDENTIFIER\tRegistry locator in the standard format of \"REGISTRY_HOST/ORGANIZATION/REPOSITORY:TAG\""
echo -e "\t\t\t\tThe leading \"REGISTRY_HOST/\" is optional and defaults to \"registry.hub.docker.com/\""
echo ""
echo -e "\tOPTION\t\tOne of:"
echo -e "\t--latest\tLookup the latest patch version of the plugin, respecting any major[.minor] of the PLUGIN_IDENTIFIER"
echo -e "\t--host\t\tParse the host out of the PLUGIN_IDENTIFIER"
echo -e "\t--org\t\tParse the organization out of the PLUGIN_IDENTIFIER"
echo -e "\t--repo\t\tParse the repository out of the PLUGIN_IDENTIFIER"
echo -e "\t--tag\t\tParse the tag out of the PLUGIN_IDENTIFIER"
echo -e "\t--exists\tCheck whether the specified reference exists on the registry"
echo -e "\t--is-release\tCheck whether the tag is for a versioned release"
}

# Identifier format: (somehost/)?ORG/IMAGE:TAG
FULL_IDENTIFIER="$1"
ARCH=$(uname -m)
YQ="$(dirname $0)/yq_${ARCH}"
[[ ! -e ${YQ} ]] && {
  >&2 echo "ERROR: Dependency yq_${ARCH} not found"
  exit 1
}

if [[ -z ${FULL_IDENTIFIER} ]] || [[ ${FULL_IDENTIFIER} =~ ^- ]]; then
  display_help
  exit 1
fi

ARGS=("$@")
for index in "${!ARGS[@]}"; do
  case ${ARGS[index]} in
    -h|--help)
        display_help
        exit 0
        ;;
    --host)
        get_host_from_ref
        exit 0
        ;;
    --org)
        get_org_from_ref
        exit 0
        ;;
    --repo)
        get_repo_from_ref
        exit 0
        ;;
    --tag)
        get_tag_from_ref
        exit 0
        ;;
    --latest)
        get_latest_stable_tag
        exit 0
        ;;
    --exists)
        tag_exists
        exit 0
        ;;
    --is-release)
        is_release_version
        exit 0
        ;;
    -*|--*)
        echo "Unknown option ${ARGS[index]}"
        display_help
      	exit 1
        ;;
  esac
done

display_help
