#!/bin/bash
# Bootstrapper to semi-automatically build avidemux from source on OSX
# (c) Mean 2009

fail()
{
    echo "** Failed at $1 **"
    exit 1
}
setupPaths()
{
# Specify the the directory where you want to install avidemux (a.k.a. the cmake_install_prefix)
# like export BASE_INSTALL_DIR="<full_path_to_installation>". This can be /usr/local or /opt/local (macports) or /sw (Fink)
    if [ "x$create_app_bundle" = "x1" ] ; then
        export BASE_INSTALL_DIR="/"
        export BASE_APP="${BUILDTOP}/Avidemux${API_VERSION}.app"
        export PREFIX="${BASE_APP}/Contents/Resources"
        if [ ! -e "${BASE_APP}/Contents/Resources" ] ; then
            mkdir -p "${BASE_APP}/Contents/Resources"
        fi
    else
        export BASE_INSTALL_DIR="${BUILDTOP}/out"
        export BASE_APP="$BASE_INSTALL_DIR"
        export PREFIX="$BASE_INSTALL_DIR"
    fi
}
Process()
{
    BASE=$1
    SOURCEDIR=$2
    EXTRA="$3"
    DEBUG=""
    BUILDER="Unix Makefiles"
    echo "**************** $1 *******************"
    if [ "x$debug" = "x1" ] ; then
        DEBUG="-DVERBOSE=1 -DCMAKE_BUILD_TYPE=Debug"
        BASE="${BASE}_debug"
        BUILDER="CodeBlocks - Unix Makefiles"
    fi
    BUILDDIR="${PWD}/${BASE}"
    FAKEROOT=""
    if [ -n "$FAKEROOT_DIR" ] ; then
        FAKEROOT="-DFAKEROOT=\"${FAKEROOT_DIR}\""
    fi
    echo "Building in \"${BUILDDIR}\" from \"${SOURCEDIR}\" with EXTRA=<$EXTRA>, DEBUG=<$DEBUG>"
    if [ "x$do_rebuild" != x1 ] ; then
        rm -Rf "$BUILDDIR"
    fi
    if [ ! -e "$BUILDDIR" ] ; then
        mkdir "$BUILDDIR" || fail mkdir
    fi
    pushd "$BUILDDIR" > /dev/null
    cmake \
    -DCMAKE_OSX_ARCHITECTURES="arm64" \
    -DCMAKE_INSTALL_PREFIX="$PREFIX" \
    -DAVIDEMUX_SOURCE_DIR="$SOURCEDIR" \
    -DAVIDEMUX_VERSION="$ADM_VERSION" \
    $FAKEROOT \
    $EXTRA \
    $FLAVOR \
    $DEBUG \
    -G "$BUILDER" \
    "$SOURCEDIR" || fail cmakeZ
    make > /tmp/log${BASE} || fail make
    if [ -n "$FAKEROOT_DIR" ] ; then
        echo "** installing to $FAKEROOT_DIR **"
    else
        echo "** installing to $PREFIX **"
    fi
    DESTDIR="$FAKEROOT_DIR" make install || fail install
    popd > /dev/null
}
printModule()
{
        value=$1
        name=$2
        if [ "x$value" = "x1" ]; then echo -e "\t$name will be built"
        else echo -e "\t$name will be skipped"
        fi
}
config()
{
        setupPaths
        echo "Build configuration :"
        echo "******************* :"
        echo -n "Build type : "
        if [ "x$debug" = "x1" ] ; then echo   "Debug build"
        else echo   "Release build"
        fi
        if [ "x$adm_version" = "x" ] ; then
            export ADM_VERSION="${MAJOR}.${MINOR}.${PATCH}"
        else
            export ADM_VERSION=$adm_version
        fi
        echo "Avidemux version : $ADM_VERSION"
        if [ "x$create_app_bundle" != "x1" ] ; then
            echo "No macOS app bundle will be created"
        fi
        if [ "x$do_rebuild" != "x1" -a "x$BASE_APP" != "x" ] ; then
            rm -Rf $BASE_APP/*
        fi
        printModule $do_core Core
        printModule $do_qt4 Qt
        printModule $do_cli Cli
        printModule $do_plugins Plugins
}
usage()
{
        echo "Bootstrap avidemux ${API_VERSION}:"
        echo "***********************"
        echo "  --help                  : Print usage"
        echo "  --no-bundle             : Don't create macOS app bundle structure"
        echo "  --nopkg                 : Don't make macOS app bundle self-contained and package it as DMG"
        echo "  --debug                 : Switch debugging on"
        echo "  --rebuild               : Preserve existing build directories"
        echo "  --output=NAME           : Specify a custom basename for dmg"
        echo "  --version=STRING        : Specify a custom Avidemux version string"
        echo "  --with-core             : Build core (default)"
        echo "  --without-core          : Don't build core"
        echo "  --with-cli              : Build cli (default)"
        echo "  --without-cli           : Don't build cli"
        echo "  --with-qt               : Build qt (default)"
        echo "  --without-qt            : Don't build qt"
        echo "  --with-plugins          : Build plugins (default)"
        echo "  --without-plugins       : Don't build plugins"
        echo "  --with-internal-liba52  : Use bundled liba52 (a52dec) instead of the system one"
        echo "  --with-external-libmad  : Use system libmad instead of the bundled one"
        echo "  --with-internal-libmp4v2: Use bundled libmp4v2 instead of the system one"
}
option_value()
{
        echo $(echo $* | cut -d '=' -f 2-)
}
validate()
{
        opt="$1"
        str="$2"
        if [ "$opt" = "adm_version" ] ; then
            reg="[^a-zA-Z0-9_.-]"
            msg="Only alphanumeric characters, hyphen, underscore and period are allowed for Avidemux version, aborting."
        elif [ "$opt" = "output" ] ; then
            reg="[^a-zA-Z0-9\ _.-]"
            msg="Only alphanumeric characters, space, hyphen, underscore and period are allowed for .dmg basename, aborting."
        else
            >&2 echo "incorrect usage of validate(), aborting."
            exit 1
        fi
        if [[ "$str" =~ $reg ]] ; then
            >&2 echo $msg
            exit 1
        fi
}

echo "** BootStrapping avidemux **"

BUILDTOP=$PWD
if [[ $BUILDTOP = *" "* ]]; then
    echo "The build directory path \"${BUILDTOP}\" contains one or more spaces."
    echo "This is unsupported by FFmpeg configure."
    fail bootstrap
fi

SRCTOP=$(cd $(dirname "$0") && pwd)

echo "Top build dir : \"${BUILDTOP}\""
echo "Top source dir : \"${SRCTOP}\""

pushd "${SRCTOP}" > /dev/null

export MAJOR=`cat avidemux_core/cmake/avidemuxVersion.cmake | grep "VERSION_MAJOR " | sed 's/..$//g' | sed 's/^.*"//g'`
export MINOR=`cat avidemux_core/cmake/avidemuxVersion.cmake | grep "VERSION_MINOR " | sed 's/..$//g' | sed 's/^.*"//g'`
export PATCH=`cat avidemux_core/cmake/avidemuxVersion.cmake | grep "VERSION_P " | sed 's/..$//g' | sed 's/^.*"//g'`
export API_VERSION="${MAJOR}.${MINOR}"

DAT=`date +"%y%m%d-%Hh%Mm"`
gt=`git log --format=oneline -1 | head -c 11`
REV="${DAT}_$gt"

popd > /dev/null

FLAVOR="-DENABLE_QT6=True"
QT_EXT="Qt6"

do_core=1
do_cli=1
do_qt4=1
do_plugins=1
do_rebuild=0
debug=0
create_app_bundle=1
create_dmg=1
external_liba52=1
external_libmad=0
external_libmp4v2=1

export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
export MACOSX_DEPLOYMENT_TARGET=$(xcrun --sdk macosx --show-sdk-version)

test -f $HOME/myCC  && export COMPILER="-DCMAKE_C_COMPILER=$HOME/myCC -DCMAKE_CXX_COMPILER=$HOME/myC++"

# Could probably do it with getopts...
while [ $# != 0 ] ;do
    config_option="$1"
    case "$config_option" in
        -h|--help)
            usage
            exit 1
            ;;
        --debug)
            debug=1
            ;;
        --rebuild)
            do_rebuild=1
            ;;
        --no-bundle)
            create_app_bundle=0
            ;;
        --nopkg)
            create_dmg=0
            ;;
        --output=*)
            dmg_base=$(option_value "$config_option")
            ;;
        --version=*)
            adm_version=$(option_value "$config_option")
            ;;
        --without-qt)
            do_qt4=0
            ;;
        --without-cli)
            do_cli=0
            ;;
        --without-plugins)
            do_plugins=0
            ;;
        --without-core)
            do_core=0
            ;;
        --with-qt)
            do_qt4=1
            ;;
        --with-cli)
            do_cli=1
            ;;
        --with-plugins)
            do_plugins=1
            ;;
        --with-core)
            do_core=1
            ;;
        --with-internal-liba52)
            external_liba52=0
            ;;
        --with-external-libmad)
            external_libmad=1
            ;;
        --with-internal-libmp4v2)
            external_libmp4v2=0
            ;;
        *)
            echo "unknown parameter $config_option"
            usage
            exit 1
            ;;
    esac
shift
done

# Probe case-sensitivity of the file system where the build directory is located.
. "${SRCTOP}/checkCaseSensitivity.sh"
isCaseSensitive || { echo "Error: build directory file system is not case-sensitive." && exit 1; }

validate adm_version "$adm_version" || exit 1
validate output "$dmg_base" || exit 1
config
# If the path to a custom Qt installation is passed via MYQT variable,
# check for a conflicting one from Homebrew.
if [ -n "$MYQT" ] && [ -f "/opt/homebrew/bin/qmake" ]; then
    echo -e "\n****************************************************************"
    echo -e "It seems that you have a Qt installation linked into /opt/homebrew,"
    echo -e "but MYQT variable is set. Please unlink it first by executing"
    echo -e "in case of Homebrew and e.g. Qt6\n"
    echo -e "\tbrew unlink qt6\n"
    echo -e "then rerun this script."
    echo -e "****************************************************************\n"
    exit 1
fi
# Homebrew offers formulae both for Qt5 and Qt6. When the version we want
# doesn't match the one linked into /opt/homebrew, the build will fail.
qmake_location=$(which qmake)
if [ "$qmake_location" = "/opt/homebrew/bin/qmake" ]; then
    linked_qt_version_major=$(qmake -query QT_VERSION)
    linked_qt_version_major=${linked_qt_version_major:0:1}
    if [ "${QT_EXT}" != "Qt${linked_qt_version_major}" ]; then
        echo -e "\n*********************** Fatal Error ****************************"
        echo -e "Qt version of the installation linked into /opt/homebrew does not"
        echo -e "match the one you are building for. If you use Homebrew, please"
        echo -e "brew link the matching one and rerun this script."
        echo -e "****************************************************************\n"
        exit 1
    fi
fi
if [ -n "$MYQT" ] && [ -f "${MYQT}/bin/qmake" ] ; then
    export QTDIR="$MYQT" # needed for translations
else
    if [ "$qmake_location" != "/opt/homebrew/bin/qmake" ]; then
        echo -e "\n****************************************************************"
        echo -e "When using Qt6 from Homebrew, please make sure it is linked into"
        echo -e "/opt/homebrew by executing\n"
        echo -e "\tbrew link qt6\n"
        echo -e "as qmake at least in Qt 6.2.0 reports a wrong path to plugins."
        echo -e "****************************************************************\n"
        exit 1
    fi
    export QTDIR="/opt/homebrew/opt/qt@6"
fi
export PATH="$PATH":"${QTDIR}/bin"
if $(which -s qmake) && [ -f "${QTDIR}/bin/qmake" ]; then
    echo "Using $QTDIR as Qt install path"
else
    echo "Error: No matching qmake executable found, aborting."
    exit 1
fi
#
POSTFIX=""
if [ "x$debug" = "x1" ] ; then
    POSTFIX="_debug"
fi
if [ "x$external_liba52" = "x1" ]; then
    EXTRA_CMAKE_DEFS="-DUSE_EXTERNAL_LIBA52=true $EXTRA_CMAKE_DEFS"
fi
if [ "x$external_libmad" = "x1" ]; then
    EXTRA_CMAKE_DEFS="-DUSE_EXTERNAL_LIBMAD=true $EXTRA_CMAKE_DEFS"
fi
if [ "x$external_libmp4v2" = "x1" ]; then
    EXTRA_CMAKE_DEFS="-DUSE_EXTERNAL_MP4V2=true $EXTRA_CMAKE_DEFS"
fi
DO_BUNDLE=""
FAKEROOT_DIR=""
if [ "x$create_app_bundle" = "x1" ] ; then
    DO_BUNDLE="-DCREATE_BUNDLE=true"
else
    DO_BUNDLE="-UCREATE_BUNDLE"
fi
if [ "x$do_core" = "x1" ] ; then
    echo "** CORE **"
    Process buildCore "${SRCTOP}/avidemux_core" $DO_BUNDLE
fi
if [ "x$do_qt4" = "x1" ] ; then
    echo "** QT **"
    Process build${QT_EXT} "${SRCTOP}/avidemux/qt4" $DO_BUNDLE
fi
if [ "x$do_cli" = "x1" ] ; then
    echo "** CLI **"
    Process buildCli "${SRCTOP}/avidemux/cli"
fi
if [ "x$do_plugins" = "x1" ] ; then
    echo "** Plugins **"
    Process buildPluginsCommon "${SRCTOP}/avidemux_plugins" "-DPLUGIN_UI=COMMON $EXTRA_CMAKE_DEFS"
fi
if [ "x$do_plugins" = "x1" -a "x$do_qt4" = "x1" ] ; then
    echo "** Plugins Qt **"
    Process buildPlugins${QT_EXT} "${SRCTOP}/avidemux_plugins" "-DPLUGIN_UI=QT4 EXTRA_CMAKE_DEFS"
fi
if [ "x$do_plugins" = "x1" -a "x$do_cli" = "x1" ] ; then
    echo "** Plugins CLI **"
    Process buildPluginsCLI "${SRCTOP}/avidemux_plugins" "-DPLUGIN_UI=CLI $EXTRA_CMAKE_DEFS"
fi
if [ "x$do_plugins" = "x1" ] ; then
    echo "** Plugins Settings **"
    Process buildPluginsSettings "${SRCTOP}/avidemux_plugins" "-DPLUGIN_UI=SETTINGS $EXTRA_CMAKE_DEFS"
fi
#
cd "$BUILDTOP"
if [ "x$create_app_bundle" = "x1" ] ; then
    mkdir "${PREFIX}/fonts"
    cp "${SRCTOP}/avidemux/qt4/cmake/osx/fonts.conf" "${PREFIX}/fonts"
    # Copy icons
    echo "Copying icons"
    cp "${SRCTOP}"/avidemux/qt4/cmake/osx/*.icns "$PREFIX"
    mkdir -p "${PREFIX}"/../MacOS
    if [ -d "${PREFIX}"/../PlugIns ]; then
        rm -Rf "${PREFIX}"/../PlugIns
    fi
    mkdir -p "${PREFIX}"/../PlugIns
    # Symlink lib directory
    if [ -e "${PREFIX}"/../lib ]; then
        rm "${PREFIX}"/../lib
    fi
    ln -s "${PREFIX}/lib" "${PREFIX}"/../
    # Symlink Qt plugins
    ln -s "${QTDIR}/share/qt/plugins/platforms" "${PREFIX}"/../PlugIns/
    ln -s "${QTDIR}/share/qt/plugins/styles" "${PREFIX}"/../PlugIns/
    # Create qt.conf
    echo "[Paths]" > "${PREFIX}"/../Resources/qt.conf
    echo "Plugins = PlugIns" >> "${PREFIX}"/../Resources/qt.conf
    if [ "x$create_dmg" = "x1" ] ; then
        if [ -e installer ]; then
            chmod -R +w installer || fail "making the old installer directory writable"
            rm -Rf installer || fail "removing the old installer directory"
        fi
        mkdir installer || fail "creating new installer directory"
        cd installer
        cmake \
        -DAVIDEMUX_VERSION="$ADM_VERSION" \
        -DAVIDEMUX_MAJOR_MINOR="${MAJOR}.${MINOR}" \
        -DDMG_BASENAME="$dmg_base" \
        -DBUILD_REV="$REV" \
        $FLAVOR \
        "${SRCTOP}/avidemux/osxInstaller" || fail "cmake"
        echo "** Preparing packaging **"
        make package
    fi
fi
echo "** ALL DONE **"
