#!/bin/bash

set -e

SCRIPT_PATH=$(dirname "$0")

source "$SCRIPT_PATH/_components_to_package.sh"
source "$SCRIPT_PATH/_common_functions.sh"

processed_once=()

# array containing [1] binaries of build-tools, [2] version in which it appeared for the 1st time, [3] conflicting debian package
build_tools_provides=()
build_tools_provides+=("aapt|1|aapt")
build_tools_provides+=("aapt2|24")
build_tools_provides+=("aidl|1|aidl")
build_tools_provides+=("apksigner|26.0.1|apksigner")
build_tools_provides+=("d8|28.0.1")
build_tools_provides+=("dexdump|1|dexdump")
build_tools_provides+=("split-select|22.0.1|split-select")
build_tools_provides+=("zipalign|19.1.0|zipalign")

# array containing [1] binaries of cmdline-tools, [2] version in which it appeared for the 1st time, [3] conflicting debian package
cmdline_tools_provides=()
cmdline_tools_provides+=("bin/apkanalyzer|1")
cmdline_tools_provides+=("bin/avdmanager|1")
cmdline_tools_provides+=("bin/lint|1")
cmdline_tools_provides+=("bin/profgen|5.0")
cmdline_tools_provides+=("bin/retrace|4.0")
cmdline_tools_provides+=("bin/screenshot2|1|android-platform-tools-base")
cmdline_tools_provides+=("bin/sdkmanager|1|sdkmanager")

update_file() {
  # $1: output file
  # $2: variable name
  # $3: variable value
  local sedscript input output
  sedscript="$3"
  input="$1"
  output="$2"

  if [ ! -s "$input" ]; then
    # echo "        Skipping missing or empty file: $input"
    return
  fi

  # shellcheck disable=SC2076
  if [ ! -f "$output" ] || [[ ! " ${processed_once[*]} " =~ " ${output} " ]]; then
    sed "$sedscript" "$input" > "$output"
    # Add file to list of files processed at least once
    processed_once+=("${output}")
  else
    sed -i "$sedscript" "$output"
  fi

}

add_alternatives() {
  local version relpath name priority
  version="$1"
  relpath="$2"
  name="$(basename "$2")"
  priority="$3"

  echo "Name: $name
Link: $(get_alternative_link_dirname)/$name
Alternative: $(get_alternative_alternative_dirname "$version")/$relpath
Priority: $priority
" >> "debian/$(get_package_name "$version").alternatives"

}

add_alternatives_ndk() {
  local version relpath name priority
  version="$1"
  relpath="$2"
  name="$(basename "$2")"
  priority="$3"

  echo "Name: $name
Link: $relpath
Alternative: $(get_alternative_alternative_dirname "$version")
Priority: $(get_alternative_priority_of_ndk "$version")
" >> "debian/$(get_package_name "$version").alternatives"

}

get_next_ndk_version() {
  # Input: r26 Output: r26b
  # Input: r26a Output: r26c
  local last_char
  last_char="${1: -1}"
  if [[ "${last_char}" =~ [a-z] ]]; then
    echo "${1:0:${#1}-1}$(echo "${last_char}" | tr '[a-y]z' '[b-z]a')"
  else
    echo "${1:0:${#1}}b"
  fi
}

generate_files() {

  local VER PATH_DIRNAME PATH_BASENAME LICENSE REPO_DIR ZIPFILE ZIPSHA1 PKG_NAME_SHORT PKG_NAME

  if [[ "$1" =~ ^ndk,* ]]; then
    VER="$(get_version_ndk_short "$1")"
  else
    VER="$(get_version "$1")"
  fi
  PATH_DIRNAME="$(get_path_dirname "$1")"
  PATH_BASENAME="$(get_path_basename "$1")"
  LICENSE="$(get_license "$1")"
  REPO_DIR="$(get_repo_dir "$1")"
  ZIPFILE="$(get_zip_filename "$1")"
  ZIPSHA1="$(get_zip_sha1 "$1")"
  PKG_NAME_SHORT="$(get_package_name_short "$1")"
  PKG_NAME="$(get_package_name "$1")"

  mkdir -p "debian/tmp/usr/share/$PKG_NAME"
  echo "$ZIPSHA1  $ZIPFILE" > "debian/tmp/usr/share/$PKG_NAME/$ZIPFILE.sha1"

  if [ ! "$VER" = "r10e" ] && [ ! "$PKG_NAME_SHORT" = "sdk-docs" ]; then
    cp -a "debian/tmp2/usr/lib/android-sdk/$PATH_DIRNAME/$PATH_BASENAME/package.xml" "debian/tmp/usr/share/$PKG_NAME/"
  fi

  cp debian/bug-script.in "debian/${PKG_NAME}.bug-script"

  update_file debian/config.in "debian/${PKG_NAME}.config" "s/%VER%/$VER/g"

  update_file "debian/${PKG_NAME_SHORT}.dirs.in" "debian/${PKG_NAME}.dirs" "s/%VER%/$VER/g"

  if [ "$VER" = "r10e" ]; then
    update_file "debian/${PKG_NAME_SHORT}-r10.install.in" "debian/${PKG_NAME}.install" "s/%VER%/$VER/g"
  else
    update_file "debian/${PKG_NAME_SHORT}.install.in" "debian/${PKG_NAME}.install" "s/%VER%/$VER/g"
  fi
  update_file "debian/${PKG_NAME_SHORT}.install.in" "debian/${PKG_NAME}.install" "s/%PKG_NAME%/${PKG_NAME}/g"
  update_file "debian/${PKG_NAME_SHORT}.install.in" "debian/${PKG_NAME}.install" "s!%PATH_DIRNAME%!$PATH_DIRNAME!g"
  update_file "debian/${PKG_NAME_SHORT}.install.in" "debian/${PKG_NAME}.install" "s/%PATH_BASENAME%/$PATH_BASENAME/g"

  update_file "debian/${PKG_NAME_SHORT}.lintian-overrides.in" "debian/${PKG_NAME}.lintian-overrides" "s/%VER%/$VER/g"

  update_file "debian/${PKG_NAME_SHORT}.postinst.in" "debian/${PKG_NAME}.postinst" "s/%VER%/$VER/g"
  update_file "debian/${PKG_NAME_SHORT}.postinst.in" "debian/${PKG_NAME}.postinst" "s!%REPO_DIR%!$REPO_DIR!g"
  update_file "debian/${PKG_NAME_SHORT}.postinst.in" "debian/${PKG_NAME}.postinst" "s/%ZIPFILE%/$ZIPFILE/g"
  update_file "debian/${PKG_NAME_SHORT}.postinst.in" "debian/${PKG_NAME}.postinst" "s!%PATH_DIRNAME%!$PATH_DIRNAME!g"
  update_file "debian/${PKG_NAME_SHORT}.postinst.in" "debian/${PKG_NAME}.postinst" "s/%PATH_BASENAME%/$PATH_BASENAME/g"
  update_file "debian/${PKG_NAME_SHORT}.postinst.in" "debian/${PKG_NAME}.postinst" "/^INS_DIR=/ s!\./!!g"

  update_file "debian/${PKG_NAME_SHORT}.postrm.in" "debian/${PKG_NAME}.postrm" "s/%VER%/$VER/g"

  update_file debian/templates.in "debian/${PKG_NAME}.templates" "s/%VER%/$VER/g"

  cp debian/copyright.header.in "debian/${PKG_NAME}.copyright"
  {
    echo ""
    echo "Files: *"
    echo "Copyright: Google Inc. "
    echo "License: $LICENSE"
    cat "debian/licenses/$LICENSE.copyright"
    echo ""
    cat debian/copyright.debian.in
  } >> "debian/${PKG_NAME}.copyright"

  #platform
  if [ "$PKG_NAME_SHORT" = "platform" ]; then
    local version version_suppl count
    version_suppl=$(echo "$1" | sed "s/,/;/g" | cut -d "~" -f 2)
    version=$(echo "$1" | sed "s/,/;/g" | cut -d "~" -f 1)

    count=$(grep -c --perl-regex "^$version\t" debian/version_list.txt)
    if [ "$count" -gt 1 ]; then
      if [ -f "debian/$PKG_NAME.substvars" ]; then rm "debian/$PKG_NAME.substvars"; fi
      for i in $(seq 1 $((count - 1))); do
        LINES="$(grep --perl-regex "^$version\t" debian/version_list.txt | grep -v --perl-regex "^$version\t.* $version_suppl\t")"
        CONFLICT_VER=$(sed "${i}q;d" <<< "$LINES" | cut -d "	" -f2)
        CONFLICT_VERBIS=$(sed "${i}q;d" <<< "$LINES" | cut -d "	" -f4 | cut -d " " -f4 | tr '[:upper:]' '[:lower:]')
        if [[ ! "$CONFLICT_VERBIS" =~ ^"$CONFLICT_VER".* ]]; then
          CONFLICT_VER="$CONFLICT_VER-$CONFLICT_VERBIS"
        else
          CONFLICT_VER="$CONFLICT_VERBIS"
        fi
        touch "debian/$PKG_NAME.substvars"
        if ! grep "google-android-platform-$VER-installer:Conflicts=" "debian/$PKG_NAME.substvars" > /dev/null; then
          echo "google-android-platform-$VER-installer:Conflicts=" >> "debian/$PKG_NAME.substvars"
        fi
        sed -i -e "/google-android-platform-$VER-installer:Conflicts=/ s/=\(.*\)/=google-android-$PKG_NAME_SHORT-$CONFLICT_VER-installer, \1/" "debian/$PKG_NAME.substvars"
        sed -i -e "/google-android-platform-$VER-installer:Conflicts=/ s/, $//" "debian/$PKG_NAME.substvars"
      done
    fi
  fi

  # build-tools
  if [ "$PKG_NAME_SHORT" = "build-tools" ]; then
    local last_version ver_increment
    local provides_bin provides_ver provided conflicting conflict ships

    last_version="$(tail -n1 <<< "${BUILD_TOOLS_VERSIONS_TO_PACKAGE}" | sort -V | cut -d "," -f 2)"
    ver_increment=$(grep -n "$1" <<< "${BUILD_TOOLS_VERSIONS_TO_PACKAGE}" | cut -d : -f 1)

    if [ -f "debian/$PKG_NAME.alternatives" ]; then rm "debian/$PKG_NAME.alternatives"; fi

    for binary in "${build_tools_provides[@]}"; do
      provides_relpath="$(cut -d "|" -f 1 <<< "$binary")"
      provides_bin="$(basename "$provides_relpath")"
      provides_ver="$(cut -d "|" -f 2 <<< "$binary")"
      conflict="$(cut -d "|" -f 3 <<< "$binary")"
      if dpkg --compare-versions "$VER" ge "$provides_ver"; then
        # Prefix version of "Provides" with 0~ (see comment for Conflicts below)
        provided="$provided, $provides_bin (= 0~$(dpkg-parsechangelog -S Version | cut -f 2 -d :))"
        ships="$ships  - $provides_bin,\${Newline}"
        if [ -n "$conflict" ]; then
          # In "Provides" we prefixed version with 0~, that way we can use >> 1
          # in "Conflicts" to ensure we conflict only with the Debian package
          # from main (and not the ones we build here). Otherwise we can't have
          # multiple versions of this package installed.
          # Stricter version constraints (like (>> ver) and (<< ver)) would
          # create problems when upgrading (would conflict the older installed
          # version).
          conflicting="$conflicting, $conflict (>> 1)"
        fi
        add_alternatives "$1" "$provides_relpath" "$((50 + ver_increment))"
      fi
    done
    provided="$(tail -c +3 <<< "$provided")"
    conflicting="$(tail -c +3 <<< "$conflicting")"
    # shellcheck disable=SC2001,SC2016
    ships="$(sed -e 's/,\${Newline}$/./' <<< "$ships")"

    if [ -f "debian/$PKG_NAME.substvars" ]; then rm "debian/$PKG_NAME.substvars"; fi

    touch "debian/$PKG_NAME.substvars"
    if ! grep "$PKG_NAME_SHORT:Provides=" "debian/$PKG_NAME.substvars" > /dev/null; then
      {
        echo "$PKG_NAME_SHORT:Provides=$provided"
        echo "$PKG_NAME_SHORT:Conflicts=$conflicting"
        echo "$PKG_NAME_SHORT:Replaces=$conflicting"
        echo "$PKG_NAME_SHORT:Ships=$ships"
      } >> "debian/$PKG_NAME.substvars"
    fi
  fi

  # cmdline-tools
  if [ "$PKG_NAME_SHORT" = "cmdline-tools" ]; then
    local last_version ver_increment
    local provides_bin provides_ver provided conflicting conflict ships

    last_version="$(tail -n1 <<< "${CMDLINE_TOOLS_VERSIONS_TO_PACKAGE}" | sort -V | cut -d "," -f 2)"
    ver_increment=$(grep -n "$1" <<< "${CMDLINE_TOOLS_VERSIONS_TO_PACKAGE}" | cut -d : -f 1)

    if [ -f "debian/$PKG_NAME.alternatives" ]; then rm "debian/$PKG_NAME.alternatives"; fi

    for binary in "${cmdline_tools_provides[@]}"; do
      provides_relpath="$(cut -d "|" -f 1 <<< "$binary")"
      provides_bin="$(basename "$provides_relpath")"
      provides_ver="$(cut -d "|" -f 2 <<< "$binary")"
      conflict="$(cut -d "|" -f 3 <<< "$binary")"
      if dpkg --compare-versions "$VER" ge "$provides_ver"; then
        # Prefix version of "Provides" with 0~ (see comment for Conflicts below)
        provided="$provided, $provides_bin (= 0~$(dpkg-parsechangelog -S Version | cut -f 2 -d :))"
        ships="$ships  - $provides_bin,\${Newline}"
        if [ -n "$conflict" ]; then
          # In "Provides" we prefixed version with 0~, that way we can use >> 1
          # in "Conflicts" to ensure we conflict only with the Debian package
          # from main (and not the ones we build here). Otherwise we can't have
          # multiple versions of this package installed.
          # Stricter version constraints (like (>> ver) and (<< ver)) would
          # create problems when upgrading (would conflict the older installed
          # version).
          conflicting="$conflicting, $conflict (>> 1)"
        fi
        add_alternatives "$1" "$provides_relpath" "$((50 + ver_increment))"
      fi

      # Add a Provides value for the virtual package 'google-android-cmdline-tools-latest-installer'
      if [ "$VER" = "$last_version" ]; then
        provided="$provided, google-android-cmdline-tools-latest-installer"
      fi

    done
    provided="$(tail -c +3 <<< "$provided")"
    conflicting="$(tail -c +3 <<< "$conflicting")"
    # shellcheck disable=SC2001,SC2016
    ships="$(sed -e 's/,\${Newline}$/./' <<< "$ships")"

    if [ -f "debian/$PKG_NAME.substvars" ]; then rm "debian/$PKG_NAME.substvars"; fi

    touch "debian/$PKG_NAME.substvars"
    if ! grep "$PKG_NAME_SHORT:Provides=" "debian/$PKG_NAME.substvars" > /dev/null; then
      {
        echo "$PKG_NAME_SHORT:Provides=$provided"
        echo "$PKG_NAME_SHORT:Conflicts=$conflicting"
        echo "$PKG_NAME_SHORT:Replaces=$conflicting"
        echo "$PKG_NAME_SHORT:Ships=$ships"
      } >> "debian/$PKG_NAME.substvars"
    fi
  fi

  # emulator & platform-tools
  if [ "$PKG_NAME_SHORT" = "emulator" ] || [ "$PKG_NAME_SHORT" = "platform-tools" ]; then
    cp "debian/$PKG_NAME_SHORT.bash-completion" "debian/$PKG_NAME.bash-completion"
    cp "debian/$PKG_NAME_SHORT.links" "debian/$PKG_NAME.links"
  fi

  # sdk-docs
  if [ "$PKG_NAME_SHORT" = "sdk-docs" ]; then
    cp "debian/$PKG_NAME_SHORT.bug-script" "debian/$PKG_NAME.bug-script"
    cp "debian/$PKG_NAME_SHORT.links" "debian/$PKG_NAME.links"
    cp "debian/$PKG_NAME_SHORT.preinst" "debian/$PKG_NAME.preinst"
    cp "debian/$PKG_NAME_SHORT.prerm" "debian/$PKG_NAME.prerm"
  fi

  # NDK
  if [ "$PKG_NAME_SHORT" = "ndk" ]; then
    if [ -f "debian/$PKG_NAME.alternatives" ]; then rm "debian/$PKG_NAME.alternatives"; fi
    add_alternatives_ndk "$1" "/usr/lib/android-ndk" "$(get_alternative_priority_of_ndk "$1")"

    # Conflict with package "android-platform-ndk", which versionning doesnt' have the
    # leading 'r'. For example 26, 26b, 26c...
    local minver maxver ANDROID_PLATFORM_NDK_VER
    ANDROID_PLATFORM_NDK_VER="${VER/r/}"
    minver="${ANDROID_PLATFORM_NDK_VER}~"
    maxver="$(get_next_ndk_version "${ANDROID_PLATFORM_NDK_VER}")~"

    conflicting="android-platform-ndk (>= $minver), android-platform-ndk (<< $maxver)"

    if [ -f "debian/$PKG_NAME.substvars" ]; then rm "debian/$PKG_NAME.substvars"; fi

    touch "debian/$PKG_NAME.substvars"
    if ! grep "$PKG_NAME_SHORT:Conflicts=" "debian/$PKG_NAME.substvars" > /dev/null; then
      echo "$PKG_NAME_SHORT:Conflicts=$conflicting" >> "debian/$PKG_NAME.substvars"
    fi

  fi

}

echo "Create package.xml files"
xsltproc "debian/scripts/make_package.xml.xsl" "repository2-1.xml"

echo "Extracting licences"
NEEDS_MIN_LICENSE_UPDATE=0
MIN_LICENSE="$(grep "^googleAndroidInstallers:LicensesMinVersion=" debian/substvars.in | cut -d "=" -f 2)"
NEW_LINES=()
mkdir -p debian/licenses debian/tmp/usr/lib/android-sdk/licenses

readarray -t LICENSES < <(grep -v "^#" debian/version_list.txt | cut -d "	" -f 5 | sort -u)

if [ "$(dpkg-parsechangelog -S Source)" = "google-android-licenses" ]; then
  # If debian/version_list.txt is empty add the licenses specified in debian/version_list.licenses
  # This can happen when in debian/control there is only google-android-licences package
  # eg. in case we invoked make_zip_package.sh with SPLIT=1
  while read -r line; do
    LICENSES+=("$(echo "$line" | cut -d "|" -f 2)")
  done < debian/version_list.licenses
fi

for license in "${LICENSES[@]}"; do
  xsltproc --stringparam license "$license" "$SCRIPT_PATH/extract-copyrights.xsl" repository2-1.xml > "debian/licenses/$license.copyright"
  # Compute sha1 of license (we need to remove newline at end of file to be consistent with:
  # https://android.googlesource.com/platform/tools/base/+/gradle_2.2.2/repository/src/main/java/com/android/repository/api/License.java)

  shasum="$(perl -p -e 'chomp if eof' "debian/licenses/$license.copyright" | sha1sum | cut -d " " -f 1)"
  if dh_listpackages | grep google-android-licenses > /dev/null; then
    echo "$shasum" > "debian/tmp/usr/lib/android-sdk/licenses/$license"
  fi

  NEW_LINES+=("$(dpkg-parsechangelog -S Version)|$license|$shasum")

  if ! grep -F "$MIN_LICENSE|$license|$shasum" debian/version_list.licenses > /dev/null; then
    echo "Couldn't find license $license with sha1sum $shasum in debian/version_list.licenses. This likely means either:"
    echo " - that the content of the license shipped in repository2-1.xml changed in the current version."
    echo " - that this license will be a new addition to google-android-licenses in the current version."
    echo " - that the version in debian/substvars.in was not updated to: $(dpkg-parsechangelog -S Version)"
    NEEDS_MIN_LICENSE_UPDATE=1
  fi

  # Reformat for inclusion in copyright file
  sed -i -e "s/^$/./" -e "s/^/ /" "debian/licenses/$license.copyright"
done

while read -r line; do
  for line_new in "${NEW_LINES[@]}"; do
    if [ "$(echo "$line" | cut -d "|" -f 2-)" = "$(echo "$line_new" | cut -d "|" -f 2-)" ]; then
      continue 2
    fi
  done
  NEEDS_MIN_LICENSE_UPDATE=1
  break
done < debian/version_list.licenses

if [ "$NEEDS_MIN_LICENSE_UPDATE" = "1" ]; then
  rm -f debian/version_list.licenses
  for line in "${NEW_LINES[@]}"; do
    echo "$line" >> debian/version_list.licenses
  done
  echo
  echo "The content of debian/version_list.licenses has been updated with new values."
  echo
  echo "You should now set the value of googleAndroidInstallers:LicensesMinVersion in debian/substvars.in to"
  echo "    $(dpkg-parsechangelog -S Version)"
  exit 1
fi

for version in ${PLATFORMS_VERSIONS_TO_PACKAGE} \
  ${BUILD_TOOLS_VERSIONS_TO_PACKAGE} \
  ${PATCHER_VERSIONS_TO_PACKAGE} \
  ${CMDLINE_TOOLS_VERSIONS_TO_PACKAGE} \
  ${PLATFORM_TOOLS_VERSIONS_TO_PACKAGE} \
  ${NDK_VERSIONS_TO_PACKAGE} \
  ${SOURCES_VERSIONS_TO_PACKAGE} \
  ${EMULATOR_VERSIONS_TO_PACKAGE} \
  ${EXTRAS_GOOGLE_AUTO_VERSIONS_TO_PACKAGE} \
  ${TOOLS_VERSIONS_TO_PACKAGE} \
  ${SDK_DOCS_VERSIONS_TO_PACKAGE}; do
  echo "    Creating autogenerated files for $version"
  generate_files "$version"
done

cp debian/google-android-licenses.copyright.in debian/google-android-licenses.copyright
