BUILDTHREADS=${BUILDTHREADS:-1}
SDK_VERSION=${SDK_VERSION:-"Default"}
NDK_VERSION=${NDK_VERSION:-"Default"}
NDK_API=${NDK_API:-"Default"}
Configuration=${Configuration:-"Default"}
XBMC_DEPENDS_ROOT=${XBMC_DEPENDS_ROOT:-"Default"}
XCODE_APP=${XCODE_APP:-"Default"}
PATH_CHANGE_REV_FILENAME=".last_success_revision"
FAILED_BUILD_FILENAME=".last_failed_revision"
#TARBALLS ENV-VAR is only used by android scripts atm
TARBALLS=${TARBALLS:-"/opt/xbmc-tarballs"}
RENDER_SYSTEM=${RENDER_SYSTEM:-"Default"}
BUILD_HOST=${BUILD_HOST:-"Default"}
BUILD_CACHE_ENTRIES=${BUILD_CACHE_ENTRIES:-2}
case "$BUILD_CACHE_ENTRIES" in *[!0-9]*) BUILD_CACHE_ENTRIES=2 ;; esac
BUILD_CACHE_NAME=".build-cache"
BUILD_CACHE_DIR=$WORKSPACE/$BUILD_CACHE_NAME

BINARY_ADDONS_ROOT=tools/depends/target
BINARY_ADDONS="binary-addons"
DEPLOYED_BINARY_ADDONS="-e /addons"

# Jenkins env variables
JENKINS_BUILD_TIMESTAMP=${BUILD_TIMESTAMP:-"unknown"}
JENKINS_BUILD_COMMIT=$(echo ${GIT_COMMIT:-"unknown"} | cut -c1-8)
JENKINS_BUILD_REVISION=${Revision:-"unknown"}
JENKINS_BUILD_ID=${BUILD_ID:-"unknown"}

JENKINS_BUILD_STRING="${JENKINS_BUILD_TIMESTAMP}-${JENKINS_BUILD_COMMIT}-${JENKINS_BUILD_REVISION}-${JENKINS_BUILD_ID}"

#set platform defaults
#$XBMC_PLATFORM_DIR matches the platform subdirs!
case $XBMC_PLATFORM_DIR in
  ios)
    DEFAULT_SDK_VERSION=26.2
    DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
    DEFAULT_CONFIGURATION="RelWithDebInfo"
    DEFAULT_XCODE_APP="Xcode-26.3.0.app"
    ;;

  tvos)
    DEFAULT_SDK_VERSION=26.2
    DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
    DEFAULT_CONFIGURATION="Release"
    DEFAULT_XCODE_APP="Xcode-26.3.0.app"
    ;;

  osx64)
    DEFAULT_SDK_VERSION=14.2
    DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
    DEFAULT_CONFIGURATION="Release"
    DEFAULT_XCODE_APP="Xcode_15.2.app"
    ;;

  osx-arm64)
    DEFAULT_SDK_VERSION=14.2
    DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
    DEFAULT_CONFIGURATION="Release"
    DEFAULT_XCODE_APP="Xcode_15.2.app"
    ;;

  android)
    DEFAULT_NDK_VERSION="28.2.13676358" # NDK package version (newer API can be inside)
    DEFAULT_NDK_API="24" # Nougat API level (24) defined in package ./sysroot/usr/include/android/api-level.h
    DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
    DEFAULT_CONFIGURATION="RelWithDebInfo"
    ;;

  linux)
    DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
    DEFAULT_CONFIGURATION="Debug"
    DEFAULT_RENDER_SYSTEM="gl"
    DEFAULT_BUILD_HOST="x86_64-linux-gnu"
  ;;

  wasm)
    DEFAULT_SDK_VERSION=5.0.6
    DEFAULT_CONFIGURATION="Release"
    DEFAULT_XBMC_DEPENDS_ROOT=$WORKSPACE/tools/depends/xbmc-depends
    DEFAULT_XCODE_APP="Xcode_15.2.app" # CI host is macos currently
  ;;

  freebsd)
    DEFAULT_CONFIGURATION="Debug"
  ;;
esac

if [ "$SDK_VERSION" == "Default" ]
then
  SDK_VERSION=$DEFAULT_SDK_VERSION
fi

if [ "$NDK_VERSION" == "Default" ]
then
  NDK_VERSION=$DEFAULT_NDK_VERSION
fi

if [ "$NDK_API" == "Default" ]
then
  NDK_API=$DEFAULT_NDK_API
fi

if [ "$XBMC_DEPENDS_ROOT" == "Default" ]
then
  XBMC_DEPENDS_ROOT=$DEFAULT_XBMC_DEPENDS_ROOT
fi

if [ "$XCODE_APP" == "Default" ]
then
  XCODE_APP=$DEFAULT_XCODE_APP
fi

# make osx environment aware of the selected xcode app
export DEVELOPER_DIR=/Applications/$XCODE_APP/Contents/Developer

if [ "$Configuration" == "Default" ]
then
  Configuration=$DEFAULT_CONFIGURATION
fi

if [ "$Configuration" != "Debug" ]
then
  DEBUG_SWITCH='--disable-debug'
fi

if [ "$RENDER_SYSTEM" == "Default" ]
then
  RENDER_SYSTEM=$DEFAULT_RENDER_SYSTEM
fi

if [ "$BUILD_HOST" == "Default" ]
then
  BUILD_HOST=$DEFAULT_BUILD_HOST
fi

#helper functions

#hash a dir based on the git revision, Configuration, SDK_PATH, NDK_PATH, NDK_VERSION, SDK_VERSION, TOOLCHAIN and XBMC_DEPENDS_ROOT
#param1 path to be hashed
function getBuildHash ()
{
  local checkPath
  checkPath="$1"
  local hashStr
  hashStr="$(git rev-list HEAD --max-count=1  -- $checkPath)"
  hashStr="$hashStr $Configuration $SDK_PATH $NDK_PATH $NDK_VERSION $SDK_VERSION $TOOLCHAIN $XBMC_DEPENDS_ROOT $XCODE_APP"
  [ -z "$DEBUG_SWITCH" ] || hashStr="$hashStr $DEBUG_SWITCH"
  echo $hashStr
}

#param1 path to be checked for changes
function pathChanged ()
{
  local ret
  local checkPath
  ret="0"

  checkPath="$1"
  if [ -e $checkPath/$PATH_CHANGE_REV_FILENAME ]
  then
    if [ "$(cat $checkPath/$PATH_CHANGE_REV_FILENAME)" != "$(getBuildHash $checkPath)" ]
    then
      ret="1"
    fi
  else
    ret="1"
  fi

  echo $ret
}

#param1 path to be tagged with hash
function tagSuccessFulBuild ()
{
  local pathToTag
  pathToTag="$1"
  # tag last successful build with revisions of the given dir
  # needs to match the checks in function getBuildHash
  echo "$(getBuildHash $pathToTag)" > $pathToTag/$PATH_CHANGE_REV_FILENAME
}

#param1 path to be tagged with hash
function tagFailedBuild ()
{
  local pathToTag
  pathToTag="$1"
  # tag last failed build with revisions of the given dir
  # needs to match the checks in function getBuildHash
  echo "$(getBuildHash $pathToTag)" > $pathToTag/$FAILED_BUILD_FILENAME
}

#param1 cached path
#param2 build hash of the cached path
function getBuildCacheEntry ()
{
  echo "$BUILD_CACHE_DIR/$(echo "$1 $2" | git hash-object --stdin)"
}

#move the untracked files of a successful build into the build cache
#param1 path to be cached
function cacheBuild ()
{
  local checkPath
  local entry
  local file
  checkPath="$1"
  if [ "$BUILD_CACHE_ENTRIES" -le 0 ]
  then
    rm -rf $BUILD_CACHE_DIR
    return
  fi
  if [ ! -e $checkPath/$PATH_CHANGE_REV_FILENAME ]
  then
    return
  fi

  entry=$(getBuildCacheEntry $checkPath "$(cat $checkPath/$PATH_CHANGE_REV_FILENAME)")
  rm -rf $entry
  mkdir -p $entry/tree
  (cd $checkPath && git ls-files --others --directory -z) > $entry/files
  while IFS= read -r -d '' file
  do
    file=${file%/}
    mkdir -p "$entry/tree/$(dirname "$file")"
    mv "$checkPath/$file" "$entry/tree/$file"
  done < $entry/files

  #the current revision's entry is about to be restored, so it does not count
  entry=$(getBuildCacheEntry $checkPath "$(getBuildHash $checkPath)")
  ls -1td $BUILD_CACHE_DIR/*/ | grep -vF "$entry/" | tail -n +$((BUILD_CACHE_ENTRIES + 1)) | xargs rm -rf
}

#move a cached build of the current revision back into place
#param1 path to be restored
#returns 1 if there is no cached build to restore
function restoreCachedBuild ()
{
  local checkPath
  local entry
  local file
  checkPath="$1"
  entry=$(getBuildCacheEntry $checkPath "$(getBuildHash $checkPath)")
  if [ ! -e $entry/files ]
  then
    return 1
  fi

  while IFS= read -r -d '' file
  do
    file=${file%/}
    if ! mv "$entry/tree/$file" "$checkPath/$file"
    then
      rm -rf $entry
      git clean -xffd $checkPath
      return 1
    fi
  done < $entry/files
  rm -rf $entry
}

#clean the workspace, keeping the depends build if tools/depends has not changed
function prepareDepends ()
{
  #clean without depends for skipping depends build if possible
  #also skip binary addons (pvr, audioencoder) as long as they are deployed in tree
  cd $WORKSPACE;git clean -xfd -e "cmake/.last_success_revision" -e "tools/depends" -e "/$BUILD_CACHE_NAME" ${DEPLOYED_BINARY_ADDONS}

  # if depends path has changed - cleanout everything and restore a cached build of this revision or do a full rebuild
  if [ "$(pathChanged $WORKSPACE/tools/depends)" == "1" ]
  then
    cacheBuild $WORKSPACE/tools/depends
    #clean up the rest too
    cd $WORKSPACE;git clean -xffd -e "/$BUILD_CACHE_NAME"
    if ! restoreCachedBuild $WORKSPACE/tools/depends
    then
      cd $WORKSPACE/tools/depends/;./bootstrap
    fi
  fi
}

function getBuildRevDateStr ()
{
  echo "${JENKINS_BUILD_STRING}"
}
