#!/usr/bin/env bash

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

ROOT=$(cd $(dirname "${BASH_SOURCE[0]}")/../..; pwd -P)

# changed from github.com/kubernetes/kubernetes/hack/lib/version.sh
# - GIT_VERSION: returned by git describe, can be used by image version
# - SEM_VERSION: version match semver format
lib::version::get_version_vars() {
  if [[ '$Format:%%$' == "%" ]]; then
    GIT_COMMIT='$Format:%H$'
    GIT_TREE_STATE='archive'
    # When a 'git archive' is exported, the '$Format:%D$' below will look
    # something like 'HEAD -> release-1.8, tag: v1.8.3' where then 'tag: '
    # can be extracted from it.
    if [[ '$Format:%D$' =~ tag:\ (v[^ ,]+) ]]; then
      GIT_VERSION="${BASH_REMATCH[1]}"
    fi
  fi


  local git=(git --work-tree "${ROOT}")

  if [[ -n ${GIT_COMMIT-} ]] || GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then
    if [[ -z ${GIT_TREE_STATE-} ]]; then
      # Check if the tree is dirty.  default to dirty
      if git_status=$("${git[@]}" status --porcelain 2>/dev/null) && [[ -z ${git_status} ]]; then
        GIT_TREE_STATE="clean"
      else
        GIT_TREE_STATE="dirty"
      fi
    fi


    if [[ -n ${GIT_VERSION-} ]] ||
        GIT_VERSION=$("${git[@]}" describe --tags --abbrev=14 "${GIT_COMMIT}^{commit}" 2>/dev/null) ||
        GIT_VERSION="v0.0.0-g"$("${git[@]}" describe --always --tags --abbrev=14 "${GIT_COMMIT}^{commit}" 2>/dev/null); then

      SEM_VERSION=${GIT_VERSION}
      # This translates the "git describe" to an actual semver.org
      # compatible semantic version that looks something like this:
      #   v1.1.0-alpha.0.6+84c76d1142ea4d
      #
      # These regexes are painful enough in sed...
      # We don't want to do them in pure shell, so disable SC2001
      # shellcheck disable=SC2001
      DASHES_IN_VERSION=$(echo "${GIT_VERSION}" | sed "s/[^-]//g")
      if [[ "${DASHES_IN_VERSION}" == "---" ]] ; then
        # shellcheck disable=SC2001
        # We have distance to subversion (v1.1.0-subversion-1-gCommitHash)
        SEM_VERSION=$(echo "${GIT_VERSION}" | sed "s/-\([0-9]\{1,\}\)-g\([0-9a-f]\{14\}\)$/.\1\+\2/")
      elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then
        # shellcheck disable=SC2001
        # We have distance to base tag (v1.1.0-1-gCommitHash)
        SEM_VERSION=$(echo "${GIT_VERSION}" | sed "s/-g\([0-9a-f]\{14\}\)$/+\1/")
      fi
      if [[ "${GIT_TREE_STATE}" == "dirty" ]]; then
        # git describe --dirty only considers changes to existing files, but
        # that is problematic since new untracked .go files affect the build,
        # so use our idea of "dirty" from git status instead.
        GIT_VERSION+="-dirty"
        SEM_VERSION+="-dirty"
      fi


      # Try to match the "git describe" output to a regex to try to extract
      # the "major" and "minor" versions and whether this is the exact tagged
      # version or whether the tree is between two tagged versions.
      if [[ "${SEM_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then
        GIT_MAJOR=${BASH_REMATCH[1]}
        GIT_MINOR=${BASH_REMATCH[2]}
        if [[ -n "${BASH_REMATCH[4]}" ]]; then
          GIT_MINOR+="+"
        fi
      fi

      # If SEM_VERSION is not a valid Semantic Version, then refuse to build.
      if ! [[ "${SEM_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
          echo "SEM_VERSION should be a valid Semantic Version. Current value: ${SEM_VERSION}"
          echo "Please see more details here: https://semver.org"
      fi
    fi

    readonly SEM_VERSION=${SEM_VERSION}
    readonly GIT_VERSION=${GIT_VERSION}
    readonly GIT_TREE_STATE=${GIT_TREE_STATE}
    readonly GIT_COMMIT=${GIT_COMMIT}
  fi
}


lib::version::get_image_version() {
    if [[ -z ${GIT_VERSION+x} ]]; then
        lib::version::get_version_vars
    fi

    echo ${GIT_VERSION}
}

lib::version::get_ldflags() {
  if [[ -z ${GIT_VERSION+x} ]]; then
    lib::version::get_version_vars
  fi

  local -a ldflags
  function add_ldflag() {
    local versionPkg=github.com/tidbcloud/aws-shared-provider/pkg/version
    local key=${1}
    local val=${2}
    # If you update these, also update the list component-base/version/def.bzl.
    ldflags+=(
      "-X '${versionPkg}.${key}=${val}'"
    )
  }

  if [[ -n ${GIT_COMMIT-} ]]; then
    add_ldflag "gitCommit" "${GIT_COMMIT}"
    add_ldflag "gitTreeState" "${GIT_TREE_STATE}"
  fi

  if [[ -n ${GIT_VERSION-} ]]; then
    add_ldflag "gitVersion" "${GIT_VERSION}"
  fi

  if [[ -n ${SEM_VERSION-} ]]; then
    add_ldflag "semVersion" "${SEM_VERSION}"
  fi


  # The -ldflags parameter takes a single string, so join the output.
  echo "${ldflags[*]-}"
}

# Get latest release branch.
# NOTE: it's not always true if remote is not origin
# or release branch format changed.
lib::version::get_latest_release_branch() {
    declare -n _branch=$1
    local git=(git --work-tree "${ROOT}")

    local branch=$($git branch -r | grep origin/release- | sort -r -V | head -n 1)

    _branch=${branch##*/}
}
