#!/bin/bash

################################################################################
#
# Prepares benchmark bundle for Linux and macOS.
#
# This is so called "works for me (tm)".
#
#
# The following settings are to be passed via config file in this directory
# or via environment variable:
#
# - STORAGE_DIRECTORY
#
#   This is directory where persistent "temporary" files will be stored.
#   For example, this is where benchmark repository is being checked out.
#
################################################################################

################################################################################
# Platform Detection

UNAME=`which uname`
if [ -z "${UNAME}" ]; then
  echo "ERROR: uname is not found, can not continue."
  exit 1
fi

KERNEL_NAME=`$UNAME -s`

################################################################################
# Configuration

if [ "${KERNEL_NAME}" == "Darwin" ]; then
  SCRIPT=$(realpath $0)
else
  SCRIPT=$(readlink -f $0)
fi

SCRIPTPATH=`dirname $SCRIPT`
BENCHMARK_VERSION="1.0"

CONFIG="${SCRIPTPATH}/config"

if [ ! -f ${CONFIG} ]; then
  echo "Configuration is not provided, will expect all settings to be"
  echo "passed via environment variables."
else
  . "${CONFIG}"
fi

################################################################################
# Initialization and sanity checks.

BITNESS="64"
if [ "${KERNEL_NAME}" == "Linux" ]; then
  MACHINE_TYPE=`${UNAME} -m`
  if [ "${MACHINE_TYPE}" == 'x86_64' ]; then
    BITNESS="64"
  else
    BITNESS="32"
  fi
elif [ "${KERNEL_NAME}" == "Darwin" ]; then
  MACHINE_TYPE="x86_64"
  BITNESS="64"
elif [[ "${KERNEL_NAME}" == "MINGW"* ]]; then
  if [ -z "${MSVC_ARCH}" ]; then
    echo "ERROR: On Windows MSVC_ARCH is to be set to either x86 or x64."
    exit 1
  fi
  if [ "${MSVC_ARCH}" == "x86" ]; then
    BITNESS="64"
  elif [ "${MSVC_ARCH}" == "x86" ]; then
    BITNESS="32"
  fi
  # TODO(sergey): Detect MSVC install somehow.
  "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" "${MSVC_ARCH}"
fi

SVN_BENCHMARK_URL="https://svn.blender.org/svnroot/bf-blender/trunk/lib/benchmarks/cycles/"
SVN_BENCHMARK_CHECKOUT_DIRECTORY="${STORAGE_DIRECTORY}/benchmark_scenes"
BUNDLE_DIRECTORY="${STORAGE_DIRECTORY}/blender-benchmark-${BENCHMARK_VERSION}"
SCENES="barbershop_interior bmw27 classroom fishy_cat koro pavillon_barcelona"
IMAGE_WIDTH=1600  # 800*2
IMAGE_HEIGHT=740  # 370*2

# Information about Blender to bundle.
if [ "${KERNEL_NAME}" == "Linux" ]; then
  if [ "${BITNESS}" == "64" ]; then
    BLENDER_PLATFORM="linux-glibc219-x86_64"
    BLENDER_PLATFORM_AND_EXTENSION="${BLENDER_PLATFORM}.tar.bz2"
  else
    BLENDER_PLATFORM="linux-glibc219-i686"
    BLENDER_PLATFORM_AND_EXTENSION="${BLENDER_PLATFORM}.tar.bz2"
  fi
elif [ "${KERNEL_NAME}" == "Darwin" ]; then
  BLENDER_PLATFORM="macOS-10.6"
  BLENDER_PLATFORM_AND_EXTENSION="${BLENDER_PLATFORM}.zip"
else
  echo "ERROR: Unsupported platform."
  exit 1
fi

# Tweak bundle directory.
BUNDLE_DIRECTORY="${BUNDLE_DIRECTORY}-${BLENDER_PLATFORM}"

# For macOS, data is installed into .app bundle.
if [ "${KERNEL_NAME}" == "Darwin" ]; then
  DATA_DIRECTORY="${BUNDLE_DIRECTORY}/blender-benchmark.app/Contents/Resources"
else
  DATA_DIRECTORY="${BUNDLE_DIRECTORY}"
fi

BLENDER_RELEASE="2.79b"
BLENDER_RELEASE_NO_LETTER=${BLENDER_RELEASE//[a-z]/}
BLENDER_RELEASE_URL="https://download.blender.org/release/Blender${BLENDER_RELEASE_NO_LETTER}"
BLENDER_RELEASE_FILE="blender-${BLENDER_RELEASE}-${BLENDER_PLATFORM_AND_EXTENSION}"
BLENDER_FULL_URL="${BLENDER_RELEASE_URL}/${BLENDER_RELEASE_FILE}"

GIT_BLENDER_REPOSITORY="git://git.blender.org/blender.git"
GIT_BENCHMARK_BRANCH="temp-benchmark"

CMAKE=`which cmake`
if [ -z "${CMAKE}" ]; then
  echo "ERROR: cmake is not found, can not continue."
  exit 1
fi

CONVERT=`which convert`
if [ -z "${CONVERT}" ]; then
  echo "ERROR: ImageMagic's convert is not found, can not continue."
  exit 1
fi

GIT=`which git`
if [ -z "${GIT}" ]; then
  echo "ERROR: Git is not found, can not continue."
  exit 1
fi

MAKE=`which make`
if [ -z "${MAKE}" ]; then
  echo "ERROR: Make is not found, can not continue."
  exit 1
fi

STRIP=`which strip`
if [ -z "${STRIP}" ]; then
  echo "ERROR: strip is not found, can not continue."
  exit 1
fi

SVN=`which svn`
if [ -z "${SVN}" ]; then
  echo "ERROR: Subversion is not found, can not continue."
  exit 1
fi

TAR=`which tar`
if [ -z "${TAR}" ]; then
  echo "ERROR: Tar is not found, can not continue."
  exit 1
fi

WGET=`which wget`
if [ -z "${WGET}" ]; then
  echo "ERROR: wget is not found, can not continue."
  exit 1
fi


# Make sure storage directory exists.
if [ -z ${STORAGE_DIRECTORY} ]; then
  echo "ERROR: STORAGE_DIRECTORY is not specified, can not continue."
  exit 1
fi
mkdir -p "${STORAGE_DIRECTORY}"

if [ -z "${BLENDER_VERSION}" ]; then
  echo ""
fi

################################################################################
# Check out benchmark repository.


if [ -d "${SVN_BENCHMARK_CHECKOUT_DIRECTORY}" ]; then
  echo "Updating benchmark scenes..."
  ${SVN} up "${SVN_BENCHMARK_CHECKOUT_DIRECTORY}"
else
  echo "Making a new checkout of scenes..."
  ${SVN} checkout "${SVN_BENCHMARK_URL}" "${SVN_BENCHMARK_CHECKOUT_DIRECTORY}"
fi

################################################################################
# Compile blender-benchmark

# We always start from scratch.
rm -rf "${BUNDLE_DIRECTORY}"
mkdir -p "${BUNDLE_DIRECTORY}"
mkdir -p "${DATA_DIRECTORY}"

SOURCE_DIRECTORY="${STORAGE_DIRECTORY}/blender.git"
BUILD_DIRECTORY="${STORAGE_DIRECTORY}/build-${BLENDER_PLATFORM}"

if [ ! -z "${CLEAN_BUILD_DIRECTORY}" ]; then
  echo "Cleaning build directory..."
  rm -rf "${BUILD_DIRECTORY}"
fi

GIT_C="${GIT} -C ${SOURCE_DIRECTORY}"

if [ ! -d "${SOURCE_DIRECTORY}" ]; then
  echo "Checking out Blender.git..."
  ${GIT} clone "${GIT_BLENDER_REPOSITORY}" "${SOURCE_DIRECTORY}"
  echo "Initializing submodules..."
  ${GIT_C} submodule update --init --recursive
fi

echo "Checking to a latest benchmark branch..."
${GIT_C} checkout ${GIT_BENCHMARK_BRANCH}
${GIT_C} pull
echo "Updatying submodules to the latest version..."
${GIT_C} submodule update --remote

if [ "${KERNEL_NAME}" == "Darwin" ]; then
  # Get precompiled libs
  cd "${SOURCE_DIRECTORY}"
  make update
fi

mkdir -p "${BUILD_DIRECTORY}"
cd "${BUILD_DIRECTORY}"
${CMAKE} \
    ${EXTRA_CMAKE_ARGS} \
    -C "${SOURCE_DIRECTORY}/build_files/cmake/config/blender_benchmark.cmake" \
    -D CMAKE_INSTALL_PREFIX="${BUNDLE_DIRECTORY}" \
    "${SOURCE_DIRECTORY}"
cd -

${MAKE} -C "${BUILD_DIRECTORY}" -j 2 install || exit 1

if [ "${KERNEL_NAME}" == "Darwin" ]; then
  sleep 1
else
  ${STRIP} -s "${BUNDLE_DIRECTORY}/blender-benchmark"
fi

################################################################################
# Package Blender and scenes into the bundle.
# After compile since these are installed into .app bundle on macOS.

# Download blender
echo "Downloading Blender..."
${WGET} -c "${BLENDER_FULL_URL}" -O "${STORAGE_DIRECTORY}/${BLENDER_RELEASE_FILE}"
echo "Unpacking Blender..."
mkdir -p "${DATA_DIRECTORY}/blender"
if [ "${KERNEL_NAME}" == "Darwin" ]; then
  rm -rf "${STORAGE_DIRECTORY}/benchmark_binary"
  unzip -q -o "${STORAGE_DIRECTORY}/${BLENDER_RELEASE_FILE}" -d "${STORAGE_DIRECTORY}/benchmark_binary"
  mv "${STORAGE_DIRECTORY}/benchmark_binary/"*"/blender.app" "${DATA_DIRECTORY}/blender/"
else
  ${TAR} -xf "${STORAGE_DIRECTORY}/${BLENDER_RELEASE_FILE}" --directory "${BUNDLE_DIRECTORY}/blender" --strip-components 1
  rm -f "${BUNDLE_DIRECTORY}/blender/blenderplayer"
fi

# Create background to stack image on.
BACKGROUND_IMAGE="${STORAGE_DIRECTORY}/background.png"
${CONVERT} -size ${IMAGE_WIDTH}x${IMAGE_HEIGHT} xc:'rgb(51,51,51)' ${BACKGROUND_IMAGE}

# Copy scenes.
mkdir -p "${DATA_DIRECTORY}/scenes"
echo "Bundling scenes..."
for scene in ${SCENES}; do
  echo "Bundling scene ${scene}..."
  cp -r "${SVN_BENCHMARK_CHECKOUT_DIRECTORY}/${scene}" "${DATA_DIRECTORY}/scenes/${scene}"
  # Leave single scene only.
  rm -f "${DATA_DIRECTORY}/scenes/${scene}/${scene}_gpu.blend"
  mv "${DATA_DIRECTORY}/scenes/${scene}/${scene}_cpu.blend" "${DATA_DIRECTORY}/scenes/${scene}/${scene}.blend"
  # Tweak image.
  if true; then
    input="${DATA_DIRECTORY}/scenes/${scene}/${scene}.png"
    input_we=`basename "${input%.*}"`
    output_scaled="${STORAGE_DIRECTORY}/${input_we}_scaled.png"
    output_compo="${STORAGE_DIRECTORY}/${input_we}.png"
    ${CONVERT} "${input}" -resize ${IMAGE_WIDTH}x${IMAGE_HEIGHT} "${output_scaled}"
    ${CONVERT} ${BACKGROUND_IMAGE} "${output_scaled}" -gravity center -composite  "${output_compo}"
    mv "${output_compo}" "${input}"
    rm ${output_scaled}
  fi
done

################################################################################
# Package.

echo "Packing bundle into archive..."
${TAR} \
  -C "${STORAGE_DIRECTORY}" \
  --exclude='*.pyc' \
  -cjf `basename ${BUNDLE_DIRECTORY}`.tar.bz2 \
  "`basename ${BUNDLE_DIRECTORY}`"
