#!/usr/bin/env bash
# completes

set -e

unsupported_binary_platform() {
  echo "Apple does not provide binary releases for $1."
  echo
  echo "You may manually install Swift and place it into:"
  echo "  $SWIFTENV_ROOT/versions/$VERSION"
  echo
  echo "Alternatively, you can force using a Ubuntu binaries by using the following:"
  echo "  $ env UBUNTU_VERSION=ubuntu15.10 swiftenv install $VERSION"
  echo
  exit 1
}

check_url() {
  status_code=$(curl -o /dev/null --silent --head --write-out '%{http_code}' "$1")
  if [ "$status_code" = "404" ]; then
    echo "$VERSION was not found on swift.org."
    echo "  $1"
    exit 1
  elif [ "$status_code" != "200" ]; then
    echo "There was a network problem retreiving $VERSION, server returned $status_code."
    echo "  $1"
    exit 1
  fi
}

get_platform() {
  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)"
      fi
    fi
    ;;
  'Darwin' )
    echo "osx"
    ;;
  * )
    echo "Unsupported Platform"
    exit 1
    ;;
  esac
}

safe_get_platform() {
  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)"
      fi
    fi
    ;;
  'Darwin' )
    echo "osx"
    ;;
  * )
    echo "unknown"
    ;;
  esac
}

install_linux_binary() {
  local VERSION_RELEASE
  local VERSION
  local URL

  VERSION="$1"
  VERSION_RELEASE="$2"
  URL="$3"

  if [ -z "$URL" ]; then
    if [ -z "$UBUNTU_VERSION" ]; then
      if command -v "lsb_release" >/dev/null 2>&1; then
        if [ $(lsb_release -is) = "Ubuntu" ]; then
          UBUNTU_VERSION="ubuntu$(lsb_release -rs)"
          if [ "$UBUNTU_VERSION" != "ubuntu15.10" ] && [ "$UBUNTU_VERSION" != "ubuntu14.04" ]; then
            unsupported_binary_platform $UBUNTU_VERSION
          fi
        else
          unsupported_binary_platform "$(lsb_release -ds)"
        fi
      else
        unsupported_binary_platform "your distribution"
      fi
    fi

    URL="https://swift.org/builds/$RELEASE/${UBUNTU_VERSION//./}/swift-$VERSION_RELEASE/swift-$VERSION_RELEASE-$UBUNTU_VERSION.tar.gz"
  fi

  if [[ "$URL" != *".tar.gz" ]]; then
    echo "$URL is not as a tar.gz as expected."
    exit 1
  fi

  check_url "$URL"

  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 OS X binary from the supplied URL
install_osx_binary() {
  local VERSION_RELEASE
  local VERSION
  local URL

  VERSION="$1"
  VERSION_RELEASE="$2"
  URL="$3"

  if [ -z "$URL" ]; then
    URL="https://swift.org/builds/$RELEASE/xcode/swift-$VERSION_RELEASE/swift-$VERSION_RELEASE-osx.pkg"
  fi

  if [[ "$URL" != *"-osx.pkg" ]]; then
    echo "$URL does not end in '-osx.pkg' as expected."
    exit 1
  fi

  check_url "$URL"

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

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

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
}

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

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
  else
    VERSION="$args"
  fi

  shift
done

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-}"
VERSION_BINARY="$VERSION"

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

if [[ "$VERSION" == "DEVELOPMENT"* ]]; then
  RELEASE="development"
elif [[ "$VERSION" == *"-SNAPSHOT-"* ]]; then
  VERSION_NUMBER=${VERSION%%-SNAPSHOT*}
  if [[ "$VERSION_NUMBER" = *"."*"."* ]]; then
    VERSION_NUMBER="$(echo $VERSION_NUMBER | sed -E 's/\.[1-9]$//')"
  fi

  RELEASE="swift-$VERSION_NUMBER-branch"
elif [[ "$VERSION" == *"-PREVIEW-"* ]]; then
  RELEASE="swift-$(echo $VERSION | sed 's/PREVIEW/preview/')"
  VERSION_BINARY="$VERSION"
elif [[ "$VERSION" == *"-GM-CANDIDATE" ]]; then
  VERSION_NUMBER=${VERSION%%-GM-CANDIDATE}
  RELEASE="swift-$VERSION_NUMBER-GM-CANDIDATE"
  VERSION_BINARY="$VERSION"
else
  RELEASE="swift-$VERSION-release"
  VERSION_BINARY="$VERSION-RELEASE"
fi

if [ "$build" == "auto" ]; then
  if [ -n "$URL" ]; then
    # URLs are always binary
    build=false
  else
    if [ -r "$SWIFTENV_SOURCE_PATH/share/swiftenv-build/$VERSION" ]; then
      build=true
    fi

    status_code=$(curl -o /dev/null --silent --head --write-out '%{http_code}' "https://swiftenv-api.fuller.li/versions/$VERSION/binaries/$(safe_get_platform)")
    if [ "$status_code" = "404" ]; then
      build=true
    elif [ "$status_code" = "200" ]; then
      URL="$(curl --silent https://swiftenv-api.fuller.li/versions/$VERSION/binaries/$(safe_get_platform) -H 'Accept: text/plain')"
      build=false
    else
      echo "There was a network problem checking for a binary release of $VERSION, server returned $status_code."
      exit 1
    fi

    if [[ "$VERSION" == *"SNAPSHOT"* ]] || [[ "$VERSION" == *"PREVIEW"* ]] || [[ "$VERSION" == *"GM"* ]]; then
      # Snapshots don't build from source
      build=false
    fi
  fi
fi

if [ "$build" == "true" ]; then
  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
    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
fi

case $(uname) in
'Linux' )
  install_linux_binary "$VERSION" "$VERSION_BINARY" "$URL"
  ;;
'Darwin' )
  install_osx_binary "$VERSION" "$VERSION_BINARY" "$URL"
  ;;
* )
  echo "There are no binary releases of Swift for $(uname). Please manually install Swift into $SWIFTENV_ROOT/versions/$VERSION"
  exit 1
  ;;
esac

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