#!/bin/bash

bold=$(tput bold)
normal=$(tput sgr0)

# Exit on errors
set -e

# Debug mode
#set -x

if [ -z "$2" ]
  then
    echo "Usage: build-portable <buildroot path> <output root path> [ <arch> ]"
    echo ""
    echo "Additional options:"
    echo ""
    echo "BRANCH: branch/commit id for checkout (default: develop)"
    echo "BUILD_THREADS: number of compiler threads to use (default: auto)"
    echo "SKIP_EXISTING: don't build/overwrite existing target packages (default: disabled)"
    echo "DEBUG: create debug build with extra logging/assertions (default: disabled)"
    echo "UPLOAD: upload created files to a remote server over sftp (default: disabled)"
    echo ""
    exit 1
fi

# Check and load SSH config for uploading (if enabled)
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

if [[ $UPLOAD ]]; then
  if [[ ! -f ${SCRIPT_DIR}/.ssh_config.user ]]; then
    echo "File ${SCRIPT_DIR}/.ssh_config.user doesn't exist"
    exit 1
  fi

  . ${SCRIPT_DIR}/.ssh_config.user

  if [[ ! $SSH_ADDRESS ]]; then
    echo "SSH_ADDRESS missing"
    exit 1
  fi

  if [[ ! $SSH_PATH ]]; then
    echo "SSH_PATH missing"
    exit 1
  fi
fi

# Source
BR_ROOT=$1
ARCH=`echo "$3" | xargs`
CREATE_LATEST=$4

# Output
OUTPUT_DIR=$2
PKG_DIR=${OUTPUT_DIR}/packages
TMP_DIR=${OUTPUT_DIR}/tmp
TMP_PKG_DIR=${TMP_DIR}/airdcpp-webclient
BUILD_CACHE_DIR=${OUTPUT_DIR}/cache

if [ ! -d $OUTPUT_DIR ]; then
  mkdir -p $OUTPUT_DIR;
fi

if [ ! -d $BUILD_CACHE_DIR ]; then
  mkdir -p $BUILD_CACHE_DIR;
fi

if [ ! -d $PKG_DIR ]; then
  mkdir -p $PKG_DIR;
fi

if [ ! -d $TMP_DIR ]; then
  mkdir -p $TMP_DIR;
fi


# CMAKE_BUILD_TYPE is also defined in the toolchain file generated by buildroot
# However, buildroot doesn't support RelWithDebInfo at the moment so we must override
# the build type here
# See http://lists.busybox.net/pipermail/buildroot/2017-August/200778.html
if [[ $DEBUG ]]; then
  CMAKE_BUILD_TYPE="Debug"
  else
  CMAKE_BUILD_TYPE="RelWithDebInfo"
fi



# echo "Creating portable archives for version ${VERSION}..."
echo ""
echo "Buildroot root: ${BR_ROOT}"
echo "Output directory: ${OUTPUT_DIR}"
echo "Mode: ${CMAKE_BUILD_TYPE}"
echo ""


FetchGit()
{
  if [[ ! $BRANCH ]]; then
    BRANCH="develop"
  fi

  echo "Using git version ${BRANCH}"

  if [ ! -d $AIR_ARCH_ROOT ]; then
    mkdir -p $AIR_ARCH_ROOT;
    cd ${AIR_ARCH_ROOT}
    git clone https://github.com/airdcpp-web/airdcpp-webclient.git ${AIR_ARCH_ROOT}
  else
    cd ${AIR_ARCH_ROOT}
  fi

  git checkout ${BRANCH}
  git pull
  git fetch --prune --tags
}

# SFTP uploading to a remote server
UploadFile()
{
  echo ""
  echo "${bold}Uploading $1...${normal}"
  sftp ${SSH_ADDRESS}:${SSH_PATH}/$2 <<< $"put $1"
}

# Call with the current arch
SetArch()
{
  case $1 in
    i786)
      ARCHSTR=32-bit
      ;;
    x86_64)
      ARCHSTR=64-bit
      ;;
    *)
      ARCHSTR=$1
      ;;
  esac

  BR_ARCH_PATH=${BR_ROOT}/$1
  AIR_ARCH_ROOT=${BUILD_CACHE_DIR}/$1
  if [[ $CMAKE_BUILD_TYPE = "Debug" ]]; then
    AIR_ARCH_ROOT=${AIR_ARCH_ROOT}-dbg
  fi

  if [ ! -d $BR_ARCH_PATH ]; then
    echo "Buildroot architecture ${BR_ARCH_PATH} doesn't exist"
    exit 1
  fi


  FetchGit

  ARCH_PKG_BASE_EXTRA=""
  if [[ $CMAKE_BUILD_TYPE = "Debug" ]]; then
    ARCH_PKG_BASE_EXTRA="-dbg"
  fi

  if [[ $BRANCH = "master" ]]; then
    PKG_SUBDIR=stable
    ARCH_GIT_VERSION=$(git describe --abbrev=0 --tags)
    ARCH_VERSION=$(cat ${AIR_ARCH_ROOT}/CMakeLists.txt | pcregrep -o1 'set \(VERSION \"([0-9]+\.[0-9]+\.[0-9]+)\"\)')

    # Additional check so that incorrect stable versions aren't being built...
    if [[ $ARCH_GIT_VERSION != $ARCH_VERSION ]]; then
      echo "${bold}Git tag/CMakeLists version mismatch (git $ARCH_GIT_VERSION, CMakeLists $ARCH_VERSION)${normal}"
      exit 1
    fi
  else
    PKG_SUBDIR=$BRANCH
    ARCH_VERSION=$(git describe --tags --abbrev=4 --dirty=-d)
  fi

  PKG_OUTPUT_DIR=${PKG_DIR}/${PKG_SUBDIR}
  ARCH_PKG_UI_VERSION=$(sh ./scripts/parse_webui_version.sh ${ARCH_VERSION})
  ARCH_PKG_BASE="airdcpp_${ARCH_VERSION}_webui-${ARCH_PKG_UI_VERSION}_${ARCHSTR}_portable${ARCH_PKG_BASE_EXTRA}"
  ARCH_PKG_PATH="$PKG_OUTPUT_DIR/$ARCH_PKG_BASE.tar.gz"

  if [ ! -d $PKG_OUTPUT_DIR ]; then
    mkdir -p $PKG_OUTPUT_DIR;
  fi

  if [[ $SKIP_EXISTING ]] && [[ -f $ARCH_PKG_PATH ]]; then
    echo "${bold}Skipping architecture $1, target file ${ARCH_PKG_PATH} exist${normal}"
    SKIP_ARCH=1
  else
    SKIP_ARCH=0
  fi
}

CreateTmpDir()
{
  if [ ! -d $OUTPUT_DIR ]; then
    mkdir -p $OUTPUT_DIR;
  fi

  if [ -d $TMP_DIR ]; then
    DeleteTmpDir
  fi

  mkdir -p $TMP_PKG_DIR;
  mkdir -p $TMP_PKG_DIR/web-resources;
}

DeleteTmpDir()
{
  #rm -rf $TMP_PKG_DIR
  rm -rf $TMP_DIR
  #rm -d $TMP_DIR
}

CreatePackage()
{
  CreateTmpDir

  echo "Packaging app..."

  cp -r ${AIR_ARCH_ROOT}/node_modules/airdcpp-webui/dist/* ${TMP_PKG_DIR}/web-resources
  cp ${AIR_ARCH_ROOT}/buildroot/resources/dcppboot.xml ${TMP_PKG_DIR}
  cp ${AIR_ARCH_ROOT}/airdcppd/airdcppd ${TMP_PKG_DIR}
  #cp -r ${AIR_ARCH_ROOT}/airdcppd/.debug ${TMP_PKG_DIR}


  # Versioned package
  ARCH_PKG_PATH=$PKG_OUTPUT_DIR/$ARCH_PKG_BASE.tar.gz
  tar czvf $ARCH_PKG_PATH -C ${TMP_DIR} airdcpp-webclient

  #echo "${bold}Package was saved to ${ARCH_PKG_PATH}${normal}"
  #APP_PKG_SUMMARY="${APP_PKG_SUMMARY}${ARCH_PKG_PATH}\n"


  # Latest package
  ARCH_LATEST_PKG_PATH=$PKG_OUTPUT_DIR/airdcpp_latest_${BRANCH}_${ARCHSTR}_portable.tar.gz
  cp $ARCH_PKG_PATH $ARCH_LATEST_PKG_PATH


  # Report
  echo "${bold}Package was saved to ${ARCH_PKG_PATH}${normal}"

  APP_PKG_SUMMARY="${APP_PKG_SUMMARY}${ARCH_PKG_PATH}\n"
  APP_PKG_SUMMARY="${APP_PKG_SUMMARY}${ARCH_LATEST_PKG_PATH}\n"

  # Upload
  if [[ $UPLOAD ]]; then
    UploadFile ${ARCH_PKG_PATH} ${PKG_SUBDIR}
    UploadFile ${ARCH_LATEST_PKG_PATH} ${PKG_SUBDIR}
  fi

  # Symbols
  CreateSymbols

  # Cleanup
  DeleteTmpDir
}

CreateSymbols()
{
  echo "Packaging symbols..."

  SYMBOLS_OUTPUT_DIR=$PKG_OUTPUT_DIR/dbg_symbols

  if [ ! -d $SYMBOLS_OUTPUT_DIR ]; then
    mkdir -p $SYMBOLS_OUTPUT_DIR;
  fi

  cp -r ${AIR_ARCH_ROOT}/airdcppd/.debug ${TMP_DIR}

  # Compress
  ARCH_SYMBOL_PKG_PATH=$SYMBOLS_OUTPUT_DIR/dbg_symbols_$ARCH_PKG_BASE.tar.gz
  tar czvf $ARCH_SYMBOL_PKG_PATH -C ${TMP_DIR} .debug

  # Report
  echo "${bold}Symbols were saved to ${ARCH_SYMBOL_PKG_PATH}${normal}"
  SYMBOLS_PKG_SUMMARY="${SYMBOLS_PKG_SUMMARY}${ARCH_SYMBOL_PKG_PATH}\n"

  # Upload
  if [[ $UPLOAD ]]; then
    UploadFile ${ARCH_SYMBOL_PKG_PATH} ${PKG_SUBDIR}/dbg_symbols
  fi
}

# Call with the current arch
BuildArch()
{
  echo ""
  echo "${bold}Configuring architecture $1...${normal}"
  SetArch $1
  if [[ $SKIP_ARCH -eq 1 ]]; then
    return 0
  fi


  if [[ ! $BUILD_THREADS ]]; then
    BUILD_THREADS=`getconf _NPROCESSORS_ONLN`
  fi

  echo "Building package ${ARCH_PKG_BASE} with ${BUILD_THREADS} threads"
  echo ""

  if [ -f ${AIR_ARCH_ROOT}/CMakeCache.txt ]; then
    rm ${AIR_ARCH_ROOT}/CMakeCache.txt
  fi

  # Define the CMAKE_CXX_FLAGS variable so that we won't get any defaults from the toolchain file
  cmake -DCMAKE_TOOLCHAIN_FILE="${BR_ARCH_PATH}/output/host/usr/share/buildroot/toolchainfile.cmake" -DSTRIP=ON -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O2 -g -DNDEBUG" -DCMAKE_CXX_FLAGS="" -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" ${AIR_ARCH_ROOT}

  make -j${BUILD_THREADS}

  CreatePackage
}

if [[ $ARCH ]]; then
  echo "${bold}Architecture ${ARCH} was specified${normal}"
  BuildArch $ARCH
else
  echo "${bold}No architecture was specified, building all${normal}"
  for d in ${BR_ROOT}/*/ ; do
    BuildArch $(basename $d)
  done
fi

echo ""
echo ""
echo ""
echo "${bold}---SUMMARY---${normal}"
echo ""
echo "${bold}Created packages:${normal}"
echo ""
echo -e "${APP_PKG_SUMMARY}"
echo ""
echo "${bold}Symbols:${normal}"
echo ""
echo -e "${SYMBOLS_PKG_SUMMARY}"
echo ""
