#!/bin/bash
#TODO: upgrade to miaou-bash

# CONSTANTS

COMMAND=''
NOVERIFY=false

# FUNCTIONS

function usage {
  echo "$(dirname $0)/$(basename $0) < --major|-M | --minor|-m | --patch|-p > [--no-verify]"
}

function parse_options {
  while [[ $# -gt 0 ]]; do
    case "$1" in
    --major | -M)
      shift 1
      COMMAND='major'
      ;;
    --minor | -m)
      shift 1
      COMMAND='minor'
      ;;
    --patch | -p)
      shift 1
      COMMAND='patch'
      ;;
    --no-verify)
      shift 1
      NOVERIFY=true
      ;;
    --help | -h)
      usage && exit 0
      ;;
    *)
      echo "Unknown option: $1"
      usage && exit 2
      ;;
    esac

    shift 1 # Move to the next argument
  done
}

function ask_for_tag {
  echo -n "Press 'M' for Major, 'm' for minor, 'p' for patch ? "
  read -rn1 input
  echo
  case "$input" in
  M)
    COMMAND='major'
    ;;
  m)
    COMMAND='minor'
    ;;
  p)
    COMMAND='patch'
    ;;
  *)
    echo >&2 "Unknown option: $input"
    exit 3
    ;;
  esac
}

function extra_options {
  extra=""
  [[ $NOVERIFY == true ]] && extra="$extra --no-verify"
  echo "$extra"
}

function assert_git_covered {
  REPOSITORY=$(git config --get remote.origin.url)
  if [[ "$?" -ne 0 ]]; then
    echo 'no remote origin defined yet, please perform: git remote add'
    exit 1
  fi
}

function assert_git_clean {
  [[ -n $(git status -s) ]] &&
    echo >&2 "git commit required, please do so before processing further" &&
    exit 2
}

function assert_git_pull {
  git remote update
  [[ -n $(git status -su no) ]] &&
    echo >&2 "git pull required, please do so before processing further" &&
    exit 3
}

function git_push {
  current_branch=$(git rev-parse --abbrev-ref HEAD)
  push_needed=$(git rev-list --branches --not --remotes | wc -l)
  if [[ $push_needed -ne 0 ]]; then
    echo 'git push needed'
    git push --set-upstream origin "$current_branch" $(extra_options)
    echo 'git push done'
    echo '-------------'
  fi
}

function latest_tagged_version {
  LAST_TAG=$(git rev-list --tags --max-count=1 2>/dev/null)
  if [[ $? -eq 0 && -n "$LAST_TAG" ]]; then
    echo "LAST=${LAST_TAG}"
    VERSION=$(git describe --tags $LAST_TAG)
    echo "current is: $VERSION"
  else
    echo 'not yet tagged!'
    VERSION=0.0.0
  fi
}

############# main

assert_git_covered
assert_git_clean
assert_git_pull

parse_options $*
git_push
latest_tagged_version
[[ -z $COMMAND ]] && ask_for_tag

# split into array
VERSION_BITS=(${VERSION//./ })
MAJOR=${VERSION_BITS[0]:=0}
MINOR=${VERSION_BITS[1]:=0}
PATCH=${VERSION_BITS[2]:=0}

REPO_NAME=$(basename $REPOSITORY)
REPO_NAME=${REPO_NAME%.git}
if [[ $VERSION != '0.0.0' ]]; then
  echo "LATEST VERSION of '$REPO_NAME' is '$MAJOR.$MINOR.$PATCH'"
  COMMIT_ID=$(git log --format="%H" -n 1)
  if [[ $COMMIT_ID == $LAST_TAG ]]; then
    echo "cannot tag twice the same commit id : $LAST_TAG"
    exit 1
  fi
fi

case $COMMAND in
"major")
  let "MAJOR++"
  let "MINOR=0"
  let "PATCH=0"
  ;;
"minor")
  let "MINOR++"
  let "PATCH=0"
  ;;
"patch")
  let "PATCH++"
  ;;
esac

echo "show TAG"
TAG="$MAJOR.$MINOR.$PATCH"
echo "new TAG $TAG"

# check if tag exists already!
if [[ -n $(git tag -l $TAG) ]]; then
  echo "WARNING: ${TAG} already exists!"
  exit 4
fi

# check whether NPM project detected, containing package.json on root project
GIT_ROOT_FOLDER=$(dirname $(git rev-parse --git-dir))
if [[ -f "${GIT_ROOT_FOLDER}/package.json" ]]; then

  echo "package.json detected, version replaced with new tag <${TAG}>"
  if ! command -v yq &>/dev/null; then
    echo 'command <yq> not found, hint: go and fetch latest release from https://github.com/mikefarah/yq'
    exit 5
  fi

  yq -i ".version=\"$TAG\"" "${GIT_ROOT_FOLDER}/package.json"
  git add ${GIT_ROOT_FOLDER}/package.json
fi

echo $TAG >${GIT_ROOT_FOLDER}/.semver_git_tag
git add ${GIT_ROOT_FOLDER}/.semver_git_tag
echo "tagging as $TAG ..."
git commit -am "tagged as ${TAG}"
git tag $TAG
git push origin --no-verify "$current_branch" --tags $(extra_options)
echo "done"
