#!/bin/bash

# Compile engauge-digitizer and bundle it as an AppImage on CentOS 6
#
# This script is supposed to run inside a CentOS 6 environment. On a Ubuntu host machine, I used
# the following commands set up a CentOS 6 environment; you can use your own chroot method of choice instead
# or just boot the CentOS-6.7-$ARCH-LiveCD.iso in a virtual machine and run this script inside there.
# sudo apt-get install unionfs-fuse git
# git clone https://github.com/probonopd/AppImageKit.git
# cp /usr/bin/unionfs-fuse AppImageKit/AppImageAssistant.AppDir/
# sudo linux32 ./AppImageKit/AppImageAssistant.AppDir/testappimage /isodevice/boot/iso/CentOS-6.7-i386-LiveCD.iso bash
# or
# sudo linux64 ./AppImageKit/AppImageAssistant.AppDir/testappimage /isodevice/boot/iso/CentOS-6.7-x86_64-LiveCD.iso bash
# bash -ex ./subsurface.centos6.sh

# Halt on errors
set -e

# Be verbose
set -x

# Sanity checks
if [[ $LOG4CPP_HOME != *"null"* ]]; then
    echo "Releases require log4cpp_null rather than log4cpp. Stopping"
    exit
fi

if [[ -z "$QTDIR" || $QTDIR == *"qt-3"* || $QTDIR == *"qt-4"* ]] ; then
    echo "Environment variable QTDIR must point to a qt5 installation"
    exit 1
fi

# TODO: move to a library function
git_pull_rebase_helper()
{
	git reset --hard HEAD
        git pull
}

export PATH=/bin:/sbin:$PATH # For CentOS 6

if [ -z "$NO_DOWNLOAD" ] ; then
# Enable EPEL repository; needed for recent Qt and
# install dependencies
if [[ "$ARCH" = "i686" ]] ; then
    sudo yum -y install epel-release git make libtool \
        libzip-devel libxml2-devel libxslt-devel libsqlite3x-devel \
        libudev-devel libusbx-devel libcurl-devel libssh2-devel mesa-libGL-devel sqlite-devel \
        tar gzip which make mesa-libEGL coreutils grep cmake gcc gcc-c++
else
    sudo yum -y install epel-release git make libtool \
        libzip-devel libxml2-devel libxslt-devel \
        libudev-devel libusb-devel libcurl-devel libssh2-devel mesa-libGL-devel sqlite-devel \
        tar gzip which make mesa-libEGL coreutils grep cmake gcc gcc-c++
fi

# Determine which architecture should be built
if [[ "$(/bin/arch)" = "i686" ||  "$(/bin/arch)" = "x86_64" ]] ; then
	ARCH=$(/bin/arch)
else
	echo "Architecture could not be determined"
	exit 1
fi

# Now we are inside CentOS 6
grep -r "CentOS release 6" /etc/redhat-release || exit 1

# Run from home directory
cd $HOME

if [ ! -d AppImages ] ; then
  git clone https://github.com/probonopd/AppImages.git
fi
cd AppImages/
git_pull_rebase_helper
cd ..

# EPEL is awesome - fresh Qt5 for old base systems
sudo yum -y install qt5-qtbase-devel  \
                    qt5-qtsvg-devel qt5-linguist qt5-qtconnectivity-devel \
                    qt5-qttools-devel qt5-qttools fftw-devel \
                    qt5-qttools-libs-help qt5-qttools-libs-clucene
fi

if [ -z "$NO_DOWNLOAD" ] ; then
# Install AppImageKit build dependencies
sudo yum -y install binutils fuse glibc-devel glib2-devel fuse-devel gcc zlib-devel libpng-devel # Fedora, RHEL, CentOS

# Build AppImageKit
if [ ! -d AppImageKit ] ; then
  git clone https://github.com/probonopd/AppImageKit.git
fi
cd AppImageKit/
git_pull_rebase_helper
cmake .
make clean
make
cd ..
fi

APP=Engauge-Digitizer
rm -rf $HOME/$APP/$APP.AppDir
mkdir -p $HOME/$APP/$APP.AppDir
cd $HOME/$APP

# Get latest engauge-digitizer and log4cpp_null projects from git
if [ ! -d engauge-digitizer ] ; then
  git clone https://github.com/markummitchell/engauge-digitizer.git
fi
cd engauge-digitizer/
git_pull_rebase_helper
cd ..

if [ ! -d log4cpp_null ] ; then
  git clone https://github.com/markummitchell/log4cpp_null.git
fi
cd log4cpp_null
git_pull_rebase_helper
cd ..

mkdir -p $HOME/$APP/$APP.AppDir/usr/bin

# Build log4cpp
LOG4CPP_HOME=$HOME/$APP/log4cpp_null
cd $LOG4CPP_HOME
qmake-qt5 log4cpp.pro
make
cd ..

# Build engauge. Version is displayed
cd $HOME/$APP/engauge-digitizer
qmake-qt5 engauge.pro DEFINES+=APPIMAGE_RELEASE CONFIG+=pdf
#Hack to nodebug
sed -i 's/ -g / /g' Makefile
make clean
make

if [ ! -e ./bin/engauge ]; then
    echo "bin/engauge executable was not created relative to directory `pwd`"
    exit 1
fi

cp ./bin/engauge $HOME/$APP/$APP.AppDir/usr/bin
cp ./src/img/bannerapp_64.xpm $HOME/$APP/$APP.AppDir/engauge.xpm

# Documentation and translation
cd help
./build.bash
cd ..

lrelease engauge.pro

mkdir -p $HOME/$APP/$APP.AppDir/usr/bin
mkdir -p $HOME/$APP/$APP.AppDir/usr/bin/translations

cp -r ./bin/documentation $HOME/$APP/$APP.AppDir/usr/bin
cp ./translations/*.qm $HOME/$APP/$APP.AppDir/usr/bin/translations

# Bundle dependency libraries into the AppDir
cd $HOME/$APP/$APP.AppDir/
cp ../../AppImageKit/AppRun .
chmod a+x AppRun

#Desktop file
cat > ./engauge.desktop <<\EOF
[Desktop Entry]
Name=Engauge Digitizer
Type=Application
Comment=Extract data from graphs
Exec=engauge
Categories=Education;Science;
Icon=engauge.xpm
EOF

# FIXME: How to find out which subset of plugins is really needed? I used strace when running the binary
mkdir -p ./usr/lib/qt5/plugins/

# QTDIR can point to personal installation of Qt which can contain Help/Print modules that may be missing from official install
PLUGINS=$QTDIR/plugins

cp -r $PLUGINS/bearer ./usr/lib/qt5/plugins/
cp -r $PLUGINS/iconengines ./usr/lib/qt5/plugins/
cp -r $PLUGINS/imageformats ./usr/lib/qt5/plugins/
cp -r $PLUGINS/platforminputcontexts ./usr/lib/qt5/plugins/
cp -r $PLUGINS/platforms ./usr/lib/qt5/plugins/
cp -r $PLUGINS/platformthemes ./usr/lib/qt5/plugins/
cp -r $PLUGINS/sqldrivers ./usr/lib/qt5/plugins/
cp -r $PLUGINS/xcbglintegrations ./usr/lib/qt5/plugins/

if [ -e $(dirname /usr/li*/libicudata.so.42) ] ; then
  LIB=$(dirname /usr/li*/libicudata.so.42)
else
  LIB=../../5.5/gc*/lib
fi
echo $LIB
cp -a $LIB/libicu* usr/lib

cp -L $LOG4CPP_HOME/lib/liblog4cpp.so.1 usr/lib
cp -L $LOG4CPP_HOME/lib/liblog4cpp.so.5 usr/lib

# Poppler library, unlike fftw3, is dynamic so library must be copied
cp -L $POPPLER_LIB/libpoppler-cpp.so usr/lib
cp -L $POPPLER_LIB/libpoppler-cpp.so.0 usr/lib
cp -L $POPPLER_LIB/libpoppler.so usr/lib
cp -L $POPPLER_LIB/libpoppler.so.61 usr/lib
cp -L $POPPLER_LIB/libpoppler-qt5.so usr/lib
cp -L $POPPLER_LIB/libpoppler-qt5.so.1 usr/lib
 
export LD_LIBRARY_PATH=./usr/lib/:../../5.5/gc*/lib/:$LD_LIBRARY_PATH
ldd $HOME/$APP/engauge-digitizer/bin/engauge | grep "=>" | awk '{print $3}'  |  xargs -I '{}' cp -v '{}' ./usr/lib || true
ldd usr/lib/qt5/plugins/platforms/libqxcb.so | grep "=>" | awk '{print $3}'  |  xargs -I '{}' cp -v '{}' ./usr/lib || true

# Copy in the indirect dependencies
FILES=$(find . -type f -executable)

for FILE in $FILES ; do
    ldd "${FILE}" | grep "=>" | awk '{print $3}' | xargs -I '{}' cp -v '{}' usr/lib || true
done

# The following are assumed to be part of the base system
rm -f usr/lib/libcom_err.so.2 || true
rm -f usr/lib/libcrypt.so.1 || true
rm -f usr/lib/libdl.so.2 || true
rm -f usr/lib/libexpat.so.1 || true
rm -f usr/lib/libfontconfig.so.1 || true
rm -f usr/lib/libgcc_s.so.1 || true
rm -f usr/lib/libglib-2.0.so.0 || true
rm -f usr/lib/libgpg-error.so.0 || true
rm -f usr/lib/libgssapi_krb5.so.2 || true
rm -f usr/lib/libgssapi.so.3 || true
rm -f usr/lib/libhcrypto.so.4 || true
rm -f usr/lib/libheimbase.so.1 || true
rm -f usr/lib/libheimntlm.so.0 || true
rm -f usr/lib/libhx509.so.5 || true
rm -f usr/lib/libICE.so.6 || true
rm -f usr/lib/libidn.so.11 || true
rm -f usr/lib/libk5crypto.so.3 || true
rm -f usr/lib/libkeyutils.so.1 || true
rm -f usr/lib/libkrb5.so.26 || true
rm -f usr/lib/libkrb5.so.3 || true
rm -f usr/lib/libkrb5support.so.0 || true
# rm -f usr/lib/liblber-2.4.so.2 || true # needed for debian wheezy
# rm -f usr/lib/libldap_r-2.4.so.2 || true # needed for debian wheezy
rm -f usr/lib/libm.so.6 || true
rm -f usr/lib/libp11-kit.so.0 || true
rm -f usr/lib/libpcre.so.3 || true
rm -f usr/lib/libpthread.so.0 || true
rm -f usr/lib/libresolv.so.2 || true
rm -f usr/lib/libroken.so.18 || true
rm -f usr/lib/librt.so.1 || true
rm -f usr/lib/libsasl2.so.2 || true
rm -f usr/lib/libSM.so.6 || true
rm -f usr/lib/libusb-1.0.so.0 || true
rm -f usr/lib/libuuid.so.1 || true
rm -f usr/lib/libwind.so.0 || true
rm -f usr/lib/libz.so.1 || true

# These seem to be available on most systems but not Ubuntu 11.04
# rm -f usr/lib/libffi.so.6 usr/lib/libGL.so.1 usr/lib/libglapi.so.0 usr/lib/libxcb.so.1 usr/lib/libxcb-glx.so.0 || true

# Delete potentially dangerous libraries
rm -f usr/lib/libstdc* usr/lib/libgobject* usr/lib/libc.so.* || true
# Do NOT delete libX* because otherwise on Ubuntu 11.04:
# loaded library "Xcursor" malloc.c:3096: sYSMALLOc: Assertion (...) Aborted

# We don't bundle the developer stuff
rm -rf usr/include || true
rm -rf usr/lib/cmake || true
rm -rf usr/lib/pkgconfig || true

strip usr/bin/* usr/lib/* || true

# Fix GDK_IS_PIXBUF errors on older distributions

# TODO: Move all cp lib things to using ldconfig because it is more robust 
# across different build system distributions and architectures.
# It is the equivalent for "find" for libraries.
cp $(ldconfig -p | grep libsasl2.so.2 | cut -d ">" -f 2 | xargs) ./usr/lib/
cp $(ldconfig -p | grep libpng12.so.0 | cut -d ">" -f 2 | xargs) ./usr/lib/
# cp $(ldconfig -p | grep libGL.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ # otherwise segfaults!?
cp $(ldconfig -p | grep libGLU.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ # otherwise segfaults!?
# Fedora 23 seemed to be missing SOMETHING from the Centos 6.7. The only message was:
# This application failed to start because it could not find or load the Qt platform plugin "xcb".
# Setting export QT_DEBUG_PLUGINS=1 revealed the cause.
# QLibraryPrivate::loadPlugin failed on "/usr/lib64/qt5/plugins/platforms/libqxcb.so" : 
# "Cannot load library /usr/lib64/qt5/plugins/platforms/libqxcb.so: (/lib64/libEGL.so.1: undefined symbol: drmGetNodeTypeFromFd)"
# Which means that we have to copy libEGL.so.1 in too
cp $(ldconfig -p | grep libEGL.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ # Otherwise F23 cannot load the Qt platform plugin "xcb"
# cp $(ldconfig -p | grep libxcb.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ 

# I have no clue why but on i386 systems this seems to be required
if [[ "$ARCH" = "i686" ]] ; then
	cp $(ldconfig -p | grep libgbm.so.1 | cut -d ">" -f 2 | xargs) ./usr/lib/ 
fi

# On openSUSE Qt is picking up the wrong libqxcb.so
# (the one from the system when in fact it should use the bundled one) - is this a Qt bug?
# Hence, we binary patch /usr/lib* to $CWD/lib* which works because at runtime,
# the current working directory is set to usr/ inside the AppImage before running the app
cd usr/ ; find . -type f -exec sed -i -e 's|/usr/lib|././/lib|g' {} \; ; cd ..

cp $(ldconfig -p | grep libfreetype.so.6 | cut -d ">" -f 2 | xargs) ./usr/lib/ # For Fedora 20

# Add desktop integration - TODO: move to a library function
XAPP=engauge
cp $HOME/$APP/engauge-digitizer/dev/linux/engauge.wrapper ./usr/bin/$XAPP.wrapper
chmod a+x ./usr/bin/$XAPP.wrapper
sed -i -e "s|Exec=$XAPP|Exec=$XAPP.wrapper|g" $XAPP.desktop

# Remove blacklisted files - TODO: move to a library function
if [ ! -e "../../AppImages/excludelist" ] ; then
  echo "excludelist missing, please install it"
  exit 1
fi
BLACKLISTED_FILES=$(cat "../../AppImages/excludelist" | sed '/^\s*$/d' | sed '/^#.*$/d')
FOUND=""
for FILE in $BLACKLISTED_FILES ; do
  FOUND=$(find "${APPDIR}" -type f -name "${FILE}" 2>/dev/null)
  echo $FOUND
  if [ ! -z "$FOUND" ] ; then
    echo "Blacklisted file ${FOUND} found"
    exit 1
  fi
done

# Workaround for:
# symbol lookup error: /usr/lib/x86_64-linux-gnu/gtk-2.0/modules/libunity-gtk-module.so: undefined symbol: g_settings_newn
rm usr/lib/qt5/plugins/platformthemes/libqgtk* || true

# Workaround for:
# GTK theme is broken
rm usr/lib/libgtk* usr/lib/libgdk* usr/lib/libpango* || true

cd ..
find $APP.AppDir/

if [[ "$ARCH" = "x86_64" ]] ; then
        APPIMAGE=digit-exe-linux-universal-64-bit-without-installer-X.Y.AppImage
fi
if [[ "$ARCH" = "i686" ]] ; then
        APPIMAGE=digit-exe-linux-universal-32-bit-without-installer-X.Y.AppImage
fi

# Put this script into the AppImage for debugging
# FIXME: The follwing line does not work
# cp $(readlink --canonicalize $0) ./$APP.AppDir/$APP.recipe

mkdir -p ../out

rm -f ../out/*.AppImage || true

# Convert the AppDir into an AppImage
rm -rf $APPIMAGE
../AppImageKit/AppImageAssistant.AppDir/package ./$APP.AppDir/ ../out/$APPIMAGE

chmod a+rwx ../out/$APPIMAGE # So that we can edit the AppImage outside of the Docker container
ls -lh ../out/$APPIMAGE
