#!/usr/bin/env bash
# Usage: swiftenv install <version>
# completes

set -e

# Check if the given version is already installed
check_installed() {
  local VERSION
  VERSION="$1"

  local PREFIX
  PREFIX="$(swiftenv-prefix "$VERSION" || true)"
  if [ -d "$PREFIX" ]; then
    echo "$VERSION is already installed."

    if [ -n "$SKIP_EXISTING" ]; then
      exit 0
    fi

    exit 1
  fi
}

get_platform() {
  if [ -n "$PLATFORM" ]; then
    echo "$PLATFORM"
    return
  fi

  case $(uname) in
  'Linux' )
    if command -v "lsb_release" >/dev/null 2>&1; then
      if [ $(lsb_release -is) = "Ubuntu" ]; then
        echo "ubuntu$(lsb_release -rs)"
      else
        echo "unsupported-platform"
      fi
    elif [ -r "/etc/lsb-release" ]; then
      echo "The `lsb_release` command line tool is missing. `/etc/lsb-release` file is found."
      exit 1
    fi
    ;;
  'Darwin' )
    echo "osx"
    ;;
  * )
    echo "unsupported-platform"
    ;;
  esac
}

install_binary() {
  local VERSION
  local URL
  VERSION="$1"
  URL="$2"

  if [[ "$URL" = *".pkg" ]]; then
    if [ "$(uname)" != "Darwin" ]; then
      echo "Cannot install .pkg from $URL on non macOS platform $(uname)."
      exit 1
    fi

    install_pkg_binary "$URL"
  elif [[ "$URL" = *".tar.gz" ]]; then
    install_tar_binary "$VERSION" "$URL"
  else
    echo "swiftenv does not know how to install $URL. Only tar.gz and pkg files are supported."
    exit 1
  fi
}

# Install a tarball binary from the supplied URL
install_tar_binary() {
  local VERSION
  local URL
  VERSION="$1"
  URL="$2"

  mkdir -p "$TMPDIR/swiftenv-$VERSION"

  echo "Downloading $URL"
  curl "$URL" -s | tar xz -C "$TMPDIR/swiftenv-$VERSION"

  DESTINATION="$SWIFTENV_ROOT/versions/$VERSION"
  mv "$TMPDIR/swiftenv-$VERSION/swift-$VERSION_RELEASE"* "$DESTINATION"
}

# Installs an `.pkg` binary from the supplied URL
install_pkg_binary() {
  local URL
  URL="$1"

  echo "Downloading $URL"
  curl -Lo "$TMPDIR/swiftenv-$VERSION.pkg" "$URL"

  sudo installer -pkg "$TMPDIR/swiftenv-$VERSION.pkg" -target /
}

# Install the given version from source
install_source() {
  VERSION="$1"

  if $clean; then
    swiftenv-build --clean "$VERSION" "$SWIFTENV_ROOT/versions/$VERSION"
  else
    swiftenv-build --no-clean "$VERSION" "$SWIFTENV_ROOT/versions/$VERSION"
  fi
}

build_version() {
  if [ -n "$URL" ]; then
    echo 'The given URL must be to a binary version of Swift, you cannot use the `--build` option with a URL.'
    exit 1
  fi

  if [ -r "$SWIFTENV_SOURCE_PATH/share/swiftenv-build/$VERSION" ]; then
    vlog "Building $VERSION from source..."
    install_source "$VERSION"
    echo "$VERSION has been installed."
    swiftenv-rehash
    swiftenv-global "${VERSION##swift-}"
    exit 0
  fi

  echo "We don't have build instructions for $VERSION."
  exit 1
}

find_binary_url_from_api() {
  vlog "Checking for a URL for the $VERSION on $(get_platform)."

  status_code=$(curl -o /dev/null --silent --head --write-out '%{http_code}' "https://swiftenv-api.fuller.li/versions/$VERSION/binaries/$(get_platform)" || true)

  if [ "$status_code" = "404" ]; then
    vlog "Did not find a binary release for $VERSION on $(get_platform)."
  elif [ "$status_code" = "200" ]; then
    URL="$(curl --silent https://swiftenv-api.fuller.li/versions/$VERSION/binaries/$(get_platform) -H 'Accept: text/plain')"
  elif [ "$status_code" = "000" ]; then
    echo "There was a problem checking for a binary release of $VERSION, could not connect to the swiftenv API."
    exit 1
  else
    echo "There was a problem checking for a binary release of $VERSION, server returned $status_code."
    exit 1
  fi
}

clean=true
list=false
snapshots=false
build=auto
verbose=false

unset SKIP_EXISTING

for args in "$@"; do
  if [ "$args" = "--no-clean" ]; then
    clean=false
  elif [ "$args" = "--clean" ]; then
    clean=true
  elif [ "$args" = "--list" ]; then
    list=true
  elif [ "$args" = "--list-snapshots" ]; then
    list=true
    snapshots=true
  elif [ "$args" = "--complete" ]; then
    list=true
  elif [ "$args" = "--build" ]; then
    build=true
  elif [ "$args" = "--no-build" ]; then
    build=false
  elif [ "$args" = "--skip-existing" ] || [ "$args" = "-s" ]; then
    SKIP_EXISTING=true
  elif [ "$args" = "--verbose" ]; then
    verbose=true
  else
    VERSION="$args"
  fi

  shift
done

vlog() {
  if $verbose; then
    echo "$1"
  fi
}

if $list; then
  if $snapshots; then
    curl -H 'Accept: text/plain' "https://swiftenv-api.fuller.li/versions?snapshot=true&platform=$(get_platform)"
    exit
  fi

  swiftenv-build --definitions
  exit
fi

mkdir -p "$SWIFTENV_ROOT/versions"
if [ -z "$VERSION" ] ; then
  VERSION="$(swiftenv-version-name --dont-check)"

  if [ "$VERSION" == "system" ]; then
    echo "Usage: swiftenv install <version>"
    exit 1
  fi
fi

if [ -z "$TMPDIR" ] ; then
  export TMPDIR=/tmp
fi

if [[ "$VERSION" == "https://"* ]]; then
  URL="$VERSION"
  VERSION="${URL##*/}"
  VERSION="${VERSION%-*}"
fi

VERSION="${VERSION##swift-}"

check_installed "$VERSION"

# Install Binary
if ([ "$build" == "auto" ] || [ "$build" == "false" ]); then
  if [ -z "$URL" ]; then
    # Check for locally cached URL
    PROFILE="$SWIFTENV_SOURCE_PATH/share/swiftenv-install/$VERSION"
    if [ -r "$PROFILE" ]; then
      source "$PROFILE"
    fi
  fi

  if [ -z "$URL" ]; then
    find_binary_url_from_api
  fi

  if [ "$URL" ]; then
    vlog "Installing $VERSION from $URL on $(get_platform)."
    install_binary "$VERSION" "$URL"
  elif [ "$build" == "false" ]; then
    echo "Could not find a binary release of $VERSION."
    exit 1
  elif [ "$build" == "auto" ]; then
    build="true"
  fi
fi


# Install Source
if [ "$build" == "true" ]; then
  build_version
fi

echo "$VERSION has been installed."
swiftenv-rehash
swiftenv-global "$VERSION"
