#!/usr/bin/env bash

# Copyright 2018 The Fuchsia Authors
#
# Use of this source code is governed by a MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT

readonly SCRIPT_DIR="$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
readonly ZIRCON_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
readonly PREBUILTS_DIR="$(cd "${ZIRCON_ROOT}/prebuilt" && pwd)"
readonly DOWNLOAD_DIR="${PREBUILTS_DIR}/downloads"
readonly ENSURE_FILE="${PREBUILTS_DIR}/zircon.ensure"
readonly VERSIONS_FILE="${PREBUILTS_DIR}/zircon.versions"
readonly URL_PREFIX="https://storage.googleapis.com/fuchsia"

# This script assumes that ENSURE_FILE and VERSIONS_FILE match up.
# The update-prebuilt-versions script ensures that they do.  When a
# cipd binary is available, ENSURE_FILE controls the downloads.
# Otherwise, VERSIONS_FILE controls the downloads.  In both cases we
# write $DOWNLOAD_DIR/$PACKAGE.stamp files with the versions from
# VERSIONS_FILE on faith that that's what we just unpacked.

cipd_ok=true
case "$#:$1" in
0:)
  mode=update
  ;;
1:--verify)
  mode=verify
  ;;
1:--list)
  mode=list
  ;;
1:--no-cipd)
  mode=update
  cipd_ok=false
  ;;
*)
  echo >&2 "Usage: $0 [--verify|--list|--no-cipd]"
  exit 1
  ;;
esac
readonly cipd_ok

case "$(uname)-$(uname -m)" in
Darwin-x86_64)
  PLATFORM=mac-amd64
  ;;
Linux-x86_64)
  PLATFORM=linux-amd64
  ;;
Linux-aarch64)
  PLATFORM=linux-arm64
  ;;
*)
  echo 'Unknown operating system.'
  exit 1
  ;;
esac
readonly PLATFORM

update_stamp() {
  local -r package="$1" version="$2" download_file="$3"
  local -r stamp="${DOWNLOAD_DIR}/${download_file%.*}.stamp"
  mkdir -p "$(dirname "$stamp")" && echo "$version" > "$stamp"
}

verify_stamp() {
  local verbose=false
  if [[ "$1" = "--verbose" ]]; then
    verbose=true
    shift
  fi
  local -r package="$1" version="$2" download_file="$3"
  local -r stamp="${DOWNLOAD_DIR}/${download_file%.*}.stamp"
  local stamp_version
  if [[ -r "$stamp" ]]; then
    stamp_version="$(< "$stamp")"
  else
    stamp_version="missing"
  fi
  if [[ "$stamp_version" = "$version" ]]; then
    return 0
  fi
  if $verbose; then
    echo "WARNING: unpacked $package $stamp_version != current $version"
  fi
  return 1
}

list_package() {
  local -r package="$1" version="$2" download_file="$3" single_file="$4"
  local -r package_suffix="$5"
  local -r stamp="${DOWNLOAD_DIR}/${download_file%.*}.stamp"
  local stamp_version
  if [[ -r "$stamp" ]]; then
    stamp_version="$(< "$stamp")"
  else
    stamp_version="missing"
  fi
  local installed="${stamp_version:-missing}"
  if [[ "$installed" = "$version" ]]; then
    installed="current"
  fi
  echo "$package$package_suffix" "installed=$installed" "current=$version"
}

verify_file() {
  local -r file="$1"
  local -r sum="$2"
  shasum --binary --check --status <<EOF
$sum *$file
EOF
}

download_package() {
  local -r package="$1" version="$2" download_file="$3" single_file="$4"
  local -r package_suffix="$5"
  local -r url="${URL_PREFIX}/${package}${package_suffix}/${version}"
  local -r download_file_with_dir="${DOWNLOAD_DIR}/${download_file}"

  # If the stamp file says it's already in place, do nothing more.
  verify_stamp "$package" "$version" "$download_file" && return

  rm -f -- "$download_file_with_dir"
  echo "Downloading $url"
  curl --progress-bar -continue-at=- --location \
       --create-dirs --output "$download_file_with_dir" "$url" || return

  verify_file "$download_file_with_dir" "$version" || {
    echo >&2 "*** VERIFICATION ERROR ***"
    echo >&2 "*** VERIFICATION ERROR *** $download_file from $url"
    echo >&2 "*** VERIFICATION ERROR *** Not using the file!"
    return 1
  }

  echo "Unpacking $download_file"
  if $single_file; then
    # The archive contains .cipd* metadata files and a single real file
    # whose name is the same as the basename of the package.
    unzip -q -o -d "$DOWNLOAD_DIR" "$download_file_with_dir" \
          "${package##*/}" || return
  else
    local -r dir="${download_file_with_dir%.zip}"
    rm -rf -- "$dir"
    unzip -q -d "$dir" "$download_file_with_dir" || return
  fi

  update_stamp "$package" "$version" "$download_file"
}

for_each_package() {
  local package version download_file single_file package_suffix status=0
  while read package version; do
    case "$package" in
    ''|\#*)
      continue
      ;;
    tools/*/${PLATFORM})
      # These are standalone executables contained in a .zip file.
      package="${package%/*}"
      download_file="${package#tools/}.zip"
      single_file=true
      package_suffix="/${PLATFORM}"
      ;;
    */${PLATFORM})
      package="${package%/*}"
      # Subdirectories are packed in .zip files.
      download_file="${package}.zip"
      single_file=false
      package_suffix="/${PLATFORM}"
      ;;
    firmware/*)
      # These are the same for every host platform.
      download_file="${package}.zip"
      single_file=false
      package_suffix=''
      ;;
    *)
      # Skip lines for other platforms.
      continue
      ;;
    esac
    "$@" "$package" "$version" "$download_file" $single_file "$package_suffix" ||
      status=$?
  done
  return $status
}

find_cipd() {
  # If the Zircon checkout is part of a jiri checkout that includes
  # //buildtools, then find cipd there.  Otherwise, if cipd is in
  # the PATH, take it from there.
  type -p "${ZIRCON_ROOT}/../buildtools/cipd" || type -p cipd
}

update_via_cipd() {
  local -r CIPD="$1" internal_access="$2"

  ensure_files="${PREBUILTS_DIR}/zircon.ensure"
  if $internal_access; then
    ensure_files+=" ${PREBUILTS_DIR}/zircon_internal.ensure"
  fi

  cat $ensure_files | "$CIPD" ensure -ensure-file - \
                                     -root "$DOWNLOAD_DIR" \
                                     -log-level warning
  rc=$?
  if [[ $rc -ne 0 ]]; then
    echo >&2 "$0: $CIPD failed.  For direct downloads, remove cipd from PATH."
    return $rc
  fi

  "$(dirname $0)/update-prebuilt-versions" --verify || {
    echo >&2 "$0: update-prebuilt-versions not run after ensure file changed!"
    return 2
  }

  # Now update the .stamp files so that --verify will be happy.
  for_each_package update_stamp < "$VERSIONS_FILE"
}

write_sysroot_path() {
  local -r package="$1" version="$2"
  if [[ "$package" = sysroot ]]; then
    echo "SYSROOT_${PLATFORM}_PATH = \$(LKMAKEROOT)/prebuilt/downloads/sysroot"
  fi
}

write_config_mk() {
  local -r internal_access="$1"
  local -r config_mk="${PREBUILTS_DIR}/config.mk"
  rm -f -- "$config_mk"
  echo > "$config_mk" "# Generated by $0.  DO NOT EDIT!"'

PREBUILT_CHECK := $(shell $(LKMAKEROOT)/scripts/download-prebuilt --verify)
ifneq (,$(strip $(PREBUILT_CHECK)))
$(warning)
$(warning $(PREBUILT_CHECK))
$(warning run scripts/download-prebuilt)
$(warning)
endif

ARCH_x86_64_TOOLCHAIN_PREFIX = $(LKMAKEROOT)/prebuilt/downloads/gcc/bin/x86_64-elf-
ARCH_arm64_TOOLCHAIN_PREFIX = $(LKMAKEROOT)/prebuilt/downloads/gcc/bin/aarch64-elf-
CLANG_TOOLCHAIN_PREFIX = $(LKMAKEROOT)/prebuilt/downloads/clang/bin/'

  for_each_package write_sysroot_path < "$VERSIONS_FILE" >> "$config_mk"

  echo >> "$config_mk" "INTERNAL_ACCESS := ${internal_access}"
}

update() {
  local CIPD
  local internal_access=false
  if $cipd_ok && CIPD="$(find_cipd)"; then
    # We have CIPD, so use it.
    if [[ "$("$CIPD" ls fuchsia_internal)" != "No matching packages." ]]; then
      internal_access=true
    fi
    update_via_cipd "$CIPD" "$internal_access" || return
  else
    # We don't have CIPD, so don't use it.
    for_each_package download_package < "$VERSIONS_FILE" || return
  fi
  write_config_mk "$internal_access"
}

verify() {
  for_each_package verify_stamp --verbose < "$VERSIONS_FILE"
}

list() {
  for_each_package list_package < "$VERSIONS_FILE"
}

$mode
