#!/bin/bash

# @param $1 {string[]} input  
# @param $2 {empty} withPre   
_getLatest() {
  if [ -z "$2" ]
  then
    local withPre="" 
  else
    local withPre="(\-[0-9]+)?"
  fi

  {
    echo "$1"
  } | {
    # Take the first satisfing entry //TODO readline?
    egrep "^v?[0-9]+(\.[0-9]+){0,2}$withPre$" | head -1
  } | {
    # Strip 'v'-s
    cut -d v -f2
  }
}

# @param $1 {major|minor|patch|release} command
# @param $2 {empty} willBePre
_semver() {
  command=$1
  willBePre=$2
  case $command in
    'major')
      if { [ -z "$prerelease" ] || [ ! -z "$willBePre" ] || [ "$patch" -ne "0" ] || [ "$minor" -ne "0" ]; }; then
        major=$(($major + 1))
      fi
      minor=0
      patch=0
      prerelease=0
    ;;
    'minor')
      if { [ -z "$prerelease" ] || [ ! -z "$willBePre" ] || [ "$patch" -ne "0" ]; }; then
        minor=$(($minor + 1))
      fi
      patch=0
      prerelease=0
    ;;
    'patch')
      if { [ -z "$prerelease" ] || [ ! -z "$willBePre" ]; }; then
        patch=$(($patch + 1))
      fi
      prerelease=0
    ;;
    'release')
      if [ -z "$willBePre" ]; then
        echo "Unknown command '$release'"
        exit 1
      fi
  
      if [ -z "$prerelease" ]
      then
        prerelease=0
        patch=$(($patch + 1))
      else
        prerelease=$(($prerelease + 1))
      fi
    ;;
    *)
      echo "Unknown command '$command'"
      exit 1
    ;;
  esac
}

command=$1
willBePre=""
if [[ $command == pre* ]]; then
  command=$(echo "$command" | cut -c4-)
  willBePre="1"
fi
case $command in
  'product')
    command="major"
    own=1
  ;;
  'feature')
    command="minor"
    own=1
  ;;
  'hotfix')
    command="patch"
    own=1
  ;;
esac

if { [ -z "$own" ] || [ ! -z "$willBePre" ]; }; then
  withPre="1"
fi
# Ways: $(</dev/stdin) $(cat) $(less <&0)
# Check from https://stackoverflow.com/a/28786207 
# file=${1--} # POSIX-compliant; ${1:--} can be used either.
if [ ! -z "$2" ]
then 
  input="$2"
elif [ ! -t 0 ]
then
  input=$(less <&0)
else
  input=$(git tag --sort=-v:refname)
fi

latest=$(_getLatest "$input" "$withPre")

if [ -z "$latest" ] && { [ -z "$withPre" ]; }; then
  # Attempt to find pre-less version
  latest=$(_getLatest "$input" "1")
fi

if [ -z "$latest" ]; then
  echo "No satisfied tag was found"
  exit 1
fi

major=$(echo "$latest" | cut -d . -f1)
minor=$(echo "$latest" | cut -d . -f2)
patchAndPre=$(echo "$latest" | cut -d . -f3)
patch=$(echo "$patchAndPre" | cut -d - -f1)
prerelease=$(echo "$patchAndPre" | cut -s -d - -f2)

if { [ ! -z "$own" ] && [ ! -z "$willBePre" ] && [ ! -z "$prerelease" ]; }; then
  case $command in
    'major')
      if { [ "$patch" -eq "0" ] && [ "$minor" -eq "0" ]; }; then
        command="release"
      fi
    ;;
    'minor')
      if [ "$patch" -eq '0' ]; then
        command="release"
      fi
    ;;
    'patch')
      command="release"
    ;;
  esac
fi
_semver "$command" "$willBePre"


[ $? -ne "0" ] && exit 1

core="$major.$minor.$patch"

if [ -z "$willBePre" ]
then
  echo "$core"
else
  pre=${prerelease:-0}
  echo "$core-$pre"
fi

