#!/bin/bash
set -e

# This is a wrapper script that runs the specific version of Android Studio that is recommended for developing in this repository.
# (This serves a similar purpose to gradlew)


function getStudioUrl() {
  propertiesFile="${scriptDir}/buildSrc/studio_versions.properties"
  version="$(grep "studio_version=" ${propertiesFile} | sed 's/[^=]*=//')"
  ideaMajorVersion="$(grep "idea_major_version=" ${propertiesFile} | sed 's/[^=]*=//')"
  buildNumber="$(grep "studio_build_number=" ${propertiesFile} | sed 's/[^=]*=//')"
  osName="$1"
  extension=""
  if [ "${osName}" == "linux" ]; then
    extension="tar.gz"
  else
    extension="zip"
  fi
  studioUrl="https://dl.google.com/dl/android/studio/ide-zips/${version}/android-studio-ide-${ideaMajorVersion}.${buildNumber}-${osName}.${extension}"
  echo "${studioUrl}"
}

acceptsLicenseAgreement="$1"
scriptDir="$(cd $(dirname $0) && pwd)"
projectDir=$scriptDir
tempDir="${scriptDir}/studio"
function getOsName() {
  unameOutput="$(uname)"
  osName=""
  if [ "${unameOutput}" == "Linux" ]; then
    osName="linux"
  else
    osName="mac"
  fi
  echo "${osName}"
}
osName="$(getOsName)"
studioUrl="$(getStudioUrl $osName)"
studioDestName="$(basename ${studioUrl})"
studioZipPath="${tempDir}/${studioDestName}"
studioUnzippedPath="$(echo ${studioZipPath} | sed 's/\.zip$//; s/\.tar.gz$//')"

function downloadFile() {
  fromUrl="$1"
  destPath="$2"
  tempPath="${destPath}.tmp"
  if [ -f "${destPath}" ]; then
    read -r -n 1 -p "File already exists. Do you want to delete and re-download? [Y/n]? " reply

    if [ ! -z "${reply}" ]; then
      # Fix missing newline
      echo
    fi

    case "${reply}" in
      [yY]|"")
        rm "${destPath}"
        ;;
      *)
    esac
  fi

  if [ -f "${destPath}" ]; then
    echo "Using existing file from ${destPath}"
  else
    echo "Downloading ${fromUrl} to ${destPath}"
    curl "${fromUrl}" > "${tempPath}"
    mv "${tempPath}" "${destPath}"
  fi
}

function findStudioMacAppPath() {
  echo "$(find "${studioUnzippedPath}" -type d -depth 1 -name "Android Studio*.app")"
}

function getLicensePath() {
  if [ "${osName}" == "mac" ]; then
    appPath="$(findStudioMacAppPath)"
    echo "${appPath}/Contents/Resources/LICENSE.txt"
  else
    echo "${studioUnzippedPath}/android-studio/LICENSE.txt"
  fi
}

function checkLicenseAgreement() {
  # TODO: Is there a more official way to check that the user accepts the license?

  licenseAcceptedPath="${studioUnzippedPath}/STUDIOW_LICENSE_ACCEPTED"

  if [ ! -f "${licenseAcceptedPath}" ]; then
    if [ "${acceptsLicenseAgreement}" == "-y" ]; then
      touch "${licenseAcceptedPath}"
    else
      read -r -n 1 -p "Do you accept the license agreement at $(getLicensePath) [Y/n]? " reply

      if [ ! -z "${reply}" ]; then
	# Fix missing newline
        echo
      fi

      case "${reply}" in
        [yY]|"")
          touch "${licenseAcceptedPath}"
          ;;
        *)
          exit 1
          ;;
      esac
    fi
  fi
}

function updateStudio() {
  # skip if already up-to-date
  if stat "${studioUnzippedPath}" >/dev/null 2>/dev/null; then
    # already up-to-date
    return
  fi

  mkdir -p "${tempDir}"
  downloadFile "${studioUrl}" "${studioZipPath}"
  echo

  echo "Removing previous installations"
  ls "${tempDir}" | grep -v "^${studioDestName}\$" | sed "s|^|${tempDir}/|" | xargs rm -rf

  echo "Unzipping"
  if [ ${studioZipPath: -7} == ".tar.gz" ]; then
    mkdir "${studioUnzippedPath}"
    tar -xvf "${studioZipPath}" -C "${studioUnzippedPath}"
  else
    unzip "${studioZipPath}" -d "${studioUnzippedPath}"
  fi
}

function ensureLocalPropertiesUpdated() {
  testPath="${projectDir}/local.properties"
  populaterCommand="./gradlew help"
  if [ ! -f "${testPath}" ]; then
    cd "$scriptDir"
    echo "Creating $testPath by running '$populaterCommand'"
    eval $populaterCommand
  fi
}

function runStudioLinux() {
  studioPath="${studioUnzippedPath}/android-studio/bin/studio.sh"
  echo "$studioPath &"
  env STUDIO_PROPERTIES="${projectDir}/development/studio/idea.properties" \
      STUDIO_VM_OPTIONS="${projectDir}/development/studio/studio.vmoptions" \
      "${studioPath}" "${projectDir}" &
}

function runStudioMac() {
  appPath="$(findStudioMacAppPath)"
  echo "open ${appPath}"
  env STUDIO_PROPERTIES="${projectDir}/development/studio/idea.properties" \
      STUDIO_VM_OPTIONS="${projectDir}/development/studio/studio.vmoptions" \
      open -a "${appPath}" "${projectDir}"
}

function runStudio() {
  if [ "${osName}" == "mac" ]; then
    runStudioMac
  else
    runStudioLinux
  fi
}

function main() {
  updateStudio
  checkLicenseAgreement
  ensureLocalPropertiesUpdated
  runStudio
}

main
