#!/bin/sh

CMAKE=cmake
ENABLE_FFMPEG=1

main() {
    cd "$(dirname $0)"

    check_command_line_args "$@"

    mktmp

    check_os

    ${os}_installdeps

    quit 0
}

check_command_line_args() {
    while [ $# -gt 0 ]; do
        case "$1" in
            -h|--help|--usage)
                usage
                quit 0
                ;;
            --no-ffmpeg)
                ENABLE_FFMPEG=
                shift
                ;;
            *)
                target=$1
                break
                ;;
        esac
    done

    if [ $# -gt 1 ]; then
        usage
        quit 1
    fi
}

check_os() {
    case "$(uname -s)" in
        Linux)
            os=linux
            ;;
        Darwin)
            os=mac
            ;;
        FreeBSD)
            os=freebsd
            ;;
        MINGW*|MSYS*)
            os=windows
            ;;
        *)
            error "Don't know how to install deps on your OS"
            ;;
    esac
}

mktmp() {
    tmp="/tmp/installdeps_$$"
    mkdir "$tmp" || quit 1
    chmod 700 "$tmp" 2>/dev/null
    trap "quit 1" PIPE HUP INT QUIT ILL TRAP KILL BUS TERM
}

quit() {
    [ -n "$tmp" ] && rm -rf "$tmp" 2>/dev/null
    exit ${1:-0}
}

usage() {
    cat <<'EOF'
Usage: [32m./installdeps [1;35m[TARGET][0m

Try to install the dependencies needed for this project appropriately on the host OS.

This program may require [1;35msudo[0m.

A cross-compile target may be specified as the only parameter, of either [1;35mm32[0m which targets the host in 32 bit mode (e.g. x86 on an amd64 host) or [1;35mwin32[0m, [1;35mMinGW-w64-i686[0m or [1;35mMinGW-w64-x86_64[0m.  [1;35mwin32[0m is an alias for [1;35mMinGW-w64-i686[0m to target Windows via MinGW.  Cross compiling for Windows is only supported on Debian/Ubuntu, Fedora, Arch Linux and MSYS2.

On MSYS2 the [1;35mMinGW-w64-clang-x86_64[0m target for CLANG64 and the [1;35mMinGW-w64-clang-i686[0m target for CLANG32 are also supported, as well as [1;35mMinGW-w64-ucrt-x86_64[0m for UCRT64.

On MSYS2 dependencies are installed for 32 or 64 bit native Windows targets based on which shell you started (the value of $MSYSTEM) unless you specify one or the other. You can specify a cross target of [1;35mm32[0m or [1;35mm64[0m as aliases for the 32 bit or 64 bit MinGW gcc targets respectively. MSYS2 POSIX layer builds are not supported.

  [1m-h, --help, --usage[0m                Show this help screen and exit.
  [1m--no-openal[0m                        Do not install OpenAL dependencies.
  [1m--no-ffmpeg[0m                        Do not install ffmpeg dependencies.

Examples:
  [32m./installdeps[0m                        # install dependencies for a host build
  [32m./installdeps [1;35mm32[0m                    # make a 32 bit binary for the host OS
  [32m./installdeps [1;35mwin32[0m                  # cross-compile for 32 bit windows (Debian/Ubuntu, Arch Linux or MSYS2)
  [32m./installdeps [1;35mMinGW-w64-i686[0m         # likewise
  [32m./installdeps [1;35mwin64[0m                  # cross-compile for 64 bit windows (Debian/Ubuntu, Arch Linux or MSYS2)
  [32m./installdeps [1;35mMinGW-w64-x86_64[0m       # likewise
EOF
}

error() {
    printf '\n[31mERROR[0m: %s.\n\n' "$1" >&2
    [ -z "$2" ] && quit 1
}

warning() {
    [ -z "$1" ] && return 0
    printf '\n[35mWARNING[0m: %s.\n\n' "$1" >&2
}


info_msg() {
    [ -z "$1" ] && return 0
    printf '\n[32mINFO[0m: %s.\n\n' "$1" >&2
}

installing() {
    echo '[32mInstalling deps...[0m'
    echo
}

check() {
    "$@"
    if [ $? -ne 0 ]; then
        error 'command failed' NOQUIT
        echo 'The failing command was:'
        echo "$@"
        quit 1
    fi
}

countdown() {
    secs=$1
    echo
    while [ "$secs" -ne 0 ]; do
        printf '%s\r' "Starting in $secs seconds..."
        sleep 1
        secs=$((secs-1))
    done
    printf '\n\n'
}

linux_installdeps() {
    # detect host architecture
    case "$(uname -a)" in
        *x86_64*)
            amd64=1
            ;;
        *i686*)
            i686=1
            ;;
    esac

    if [ -f /etc/debian_version ]; then
        debian_installdeps
    elif [ -f /etc/fedora-release ]; then
        fedora_installdeps
    elif [ -f /etc/redhat-release ] || [ -f /etc/centos-release ]; then
        rhel_installdeps
    elif [ -f /etc/solus-release ]; then
        solus_installdeps
    elif [ -f /etc/gentoo-release ]; then
        gentoo_installdeps
    elif [ -x /usr/bin/pacman ]; then
        archlinux_installdeps
    elif [ -f /etc/os-release ]; then
        case "$(. /etc/os-release; echo "${ID_LIKE:-$ID}")" in
            *suse*)
                suse_installdeps
                ;;
            nixos)
                nixos_installdeps
                ;;
            alpine)
                alpine_installdeps
                ;;
            *)
                error "Don't know how to install deps on your version of Linux"
                ;;
        esac
    else
        error "Don't know how to install deps on your version of Linux"
    fi
}

freebsd_installdeps() {
    installing

    check sudo pkg update

    pkgs="llvm-devel cmake ccache nasm ffmpeg gettext-tools gettext pkgconf sdl2 sfml wx31-gtk3 iconv zip ninja"

    [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"

    # currently the wx30 and wx31 packages produce GTK errors on CURRENT (as of 04/2019)
    check sudo pkg install -y $pkgs

    build_instructions
}

# the -j flag for make parameter, empty if 1
jobs_flag() {
    if [ $(num_cpus) -gt 1 ]; then
        echo "-j$(num_cpus)"
    fi
}

# number of CPUs to use for jobs, 1 less than total to not overload resources
num_cpus() {
    if [ -n "$_num_cpus" ]; then
        if [ $((_num_cpus - 1)) -lt 1 ]; then
            echo 1
        else
            echo $((_num_cpus - 1))
        fi
        return 0
    fi

    # determine number of CPUs and cache it
    if command -v nproc >/dev/null; then
        _num_cpus=$(nproc)
    elif [ $os = linux -o $os = windows ]; then
        _num_cpus=$(grep '^processor		*:' /proc/cpuinfo | wc -l)
    elif [ $os = mac ] || [ $os = freebsd ]; then
        _num_cpus=$(sysctl -n hw.ncpu)
    fi

    [ -z "$_num_cpus" ] && _num_cpus=1

    num_cpus
}

check_cross() {
    target=$(echo "$target" | tr 'A-Z' 'a-z')

    if [ -z "$target" ]; then
        if [ -n "$msys2" ]; then
            case "$MSYSTEM" in
                MINGW32)
                    target='mingw-w64-i686'
                    ;;
                MINGW64)
                    target='mingw-w64-x86_64'
                    ;;
                CLANG32)
                    target='mingw-w64-clang-i686'
                    ;;
                CLANG64)
                    target='mingw-w64-clang-x86_64'
                    ;;
                UCRT64)
                    target='mingw-w64-ucrt-x86_64'
                    ;;
                MSYS)
                    error 'host builds in MSYS mode are not supported, supply a target or start a MINGW shell'
                    ;;
                *)
                    error 'unknown value for $MSYSTEM: '"$MSYSTEM"' '
                    ;;
            esac
        else
            return
        fi
    fi

    case "$target" in
        win32|win64|mingw*)
            if [ -z "$arch_linux" -a -z "$msys2" -a -z "$debian" -a -z "$fedora" ]; then
                error 'win32 cross compiling targets are only supported on Debian/Ubuntu, Fedora, Arch and MSYS2 at the moment'
            fi

            case "$target" in
                win32)
                    target='mingw-w64-i686'
                    ;;
                win64)
                    target='mingw-w64-x86_64'
                    ;;
                mingw-w64-x86_64|mingw-w64-i686|mingw-w64-clang-x86_64|mingw-w64-ucrt-x86_64|mingw-w64-clang-i686)
                    ;;
                *)
                    error "target must be one of 'm32', 'win32', 'win64', or one of the MinGW/clang/ucrt targets supported by MSYS2: mingw-w64-[clang|ucrt]-(x86_64|i686)."
                    ;;
            esac
            ;;
        m32|-m32)
            target=m32
            if [ -z "$msys2" -a -z "$fedora" -a -z "$arch_linux" -a -z "$solus" -a -z "$suse" ]; then
                error '32 bit builds are only supported on Fedora, OpenSUSE, Arch, Solus and MSYS2 at the moment'
            fi

            if [ -n "$msys2" ]; then
                target='mingw-w64-i686'
            else
                cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake"
            fi
            ;;
        m64)
            if [ -z "$msys2" ]; then
                error '64 bit cross target only supported on MSYS2 at the moment'
            fi
            target='mingw-w64-x86_64'
            ;;
        *)
            error "unknown cross target: '$target' "
            ;;
    esac
}

debian_installdeps() {
    debian=1
    check_cross
    installing

    if [ -z "$target" ]; then
        sudo apt-get -qq -y update

        sfml_libs=

        for lib in graphics window network; do
            sfml_libs="$sfml_libs $(apt-cache search "libsfml-$lib" | sed 's/ - .*//' | sort -r | head -1)"
        done

        glew_lib=$(apt-cache search libglew | grep '^libglew[0-9]' | sed 's/ - .*//' | sort -r | head -1)

        sdl_lib=$(apt-cache search '^libsdl2-2.0' | sed 's/ - .*//' | sort -r | head -1)

        # not present in trusty
        if [ -n "$ENABLE_FFMPEG" ]; then
            libswresample_dev=$(apt-cache search libswresample-dev | awk '{print $1}')
        fi

        wx_libs=$(apt-cache search 'libwxgtk[0-9]' | sed 's/ - .*//')

        # Use -gtk3 variant on older distros.
        case "$wx_libs" in
            *-gtk3*)
                new_wx_libs=
                for pkg in $wx_libs; do
                    case "$pkg" in
                        *-gtk3*)
                            new_wx_libs="$new_wx_libs $pkg"
                            ;;
                    esac
                done
                wx_libs=$new_wx_libs
                ;;
        esac

        pkgs="build-essential g++ nasm cmake ccache gettext zlib1g-dev libgl1-mesa-dev libgettextpo-dev libsdl2-dev $sdl_lib libglu1-mesa-dev libglu1-mesa libgles2-mesa-dev libsfml-dev $sfml_libs $glew_lib $wx_libs libgtk2.0-dev libgtk-3-dev ccache zip ninja-build libopenal-dev"

        [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs libavcodec-dev libavformat-dev libswscale-dev libavutil-dev $libswresample_dev"

        check sudo apt-get -qy install $pkgs
    else
        case "$target" in
            mingw-w64-i686)
                target='i686-w64-mingw32.static'
                CMAKE="/usr/lib/mxe/usr/bin/i686-w64-mingw32.static-cmake"
                ;;
            mingw-w64-x86_64)
                target='x86-64-w64-mingw32.static'
                CMAKE="/usr/lib/mxe/usr/bin/x86_64-w64-mingw32.static-cmake"
                ;;
            *)
                error "unknown cross target (you shouldn't see this)"
                ;;
        esac

        pre_build='export PATH="$PATH:/usr/lib/mxe/usr/bin"'

        debian_rel=$(lsb_release -a 2>/dev/null | sed -En 's/^Codename:[[:space:]]*//p')

        case "$debian_rel" in
            bionic|stretch|trusty|xenial)
                ;;
            yakkety|zesty|artful)
                debian_rel=xenial
                ;;
            utopic|vivid|wily)
                debian_rel=trusty
                ;;
            *)
                debian_rel=bionic
                ;;
        esac

        mxe_apt_sources=/etc/apt/sources.list.d/mxeapt.list

        sudo apt-get -qq -y update

        if [ -z "$(apt-cache search '^mxe-source$')" ]; then
            if [ ! -f "$mxe_apt_sources" ]; then
                echo "deb http://pkg.mxe.cc/repos/apt $debian_rel main" | sudo -- sh -c "cat > $mxe_apt_sources"
                sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C6BF758A33A3A276 || :
            else
                error "$mxe_apt_sources exists but mxe packages are not found in apt, either delete it or fix it"
            fi
        fi

        deps="gcc zlib ffmpeg gettext sdl2 sfml openal wxwidgets openal"
        [ -n "$ENABLE_FFMPEG" ] && deps="$deps ffmpeg"

        set --
        for dep in $deps; do
            set -- "$@" "mxe-${target}-$dep"
        done
        check sudo apt-get --allow-unauthenticated -qq -y update

        # Native wx-common needed for wxrc executable.
        check sudo apt-get --allow-unauthenticated -qy install build-essential cmake ninja-build ccache wx-common git "$@"

        # The ccache symlink is broken in some versions of these mxe packages.
        ccache_link=/usr/lib/mxe/.ccache/bin/ccache

        if [ ! -e "$ccache_link" ]; then
            sudo mkdir -p ${ccache_link%/*}
            sudo ln -sf /usr/bin/ccache "$ccache_link"
        fi

        # get the necessary win32 headers
        git submodule update --init --remote --recursive
    fi

    build_instructions
}

fedora_installdeps() {
    fedora=1
    ffmpeg=ffmpeg-devel
    rpms_installed=

    check_cross
    installing

    warning=

    if [ -n "$ENABLE_FFMPEG" ]; then
        # using --nogpgcheck with dnf because keys can be a problem on rawhide

        fedora_release=$(rpm -E %fedora)
        tries=3
        curdir=$(pwd)

        # make sure rpmfusion is installed for ffmpeg
        while [ $tries -gt 0 ]; do
            mkdir -p "${tmp}/fusion"
            cd "${tmp}/fusion"
            if ! curl -fLO https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-${fedora_release}.noarch.rpm; then
                fedora_release=$((fedora_release - 1))
                tries=$((tries - 1))
                continue
            fi
            if ! curl -fLO https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-${fedora_release}.noarch.rpm; then
                tries=0
                break
            fi
            # check if already installed
            if rpm -q rpmfusion-free-release-${fedora_release} >/dev/null 2>&1 && rpm -q rpmfusion-nonfree-release-${fedora_release} >/dev/null 2>&1; then
                info_msg 'rpmfusion already installed, good'
                break
            fi
            # otherwise try to install
            if ! sudo rpm --nodeps -Uvh ./rpmfusion-*.rpm; then
                tries=0
                break
            fi
            break
        done
        cd "$curdir"
        if [ $tries -eq 0 ]; then
            warning 'installing rpmfusion repos failed, continuing without ffmpeg'
            no_ffmpeg=1
        fi
    fi

    # non-multiarch packages first
    check sudo dnf -y --nogpgcheck --best --allowerasing install gcc gcc-c++ make cmake ccache git nasm redhat-rpm-config pkgconfig ccache ninja-build

    # try to install multiarch libgcc, glibc-devel and pkgconfig if available
    if [ -n "$amd64" ]; then
        for pkg in pkgconfig libgcc glibc-devel; do
            if [ "$target" = m32 ]; then
                sudo dnf -y --nogpgcheck --best --allowerasing install "$pkg".i686
            else
                sudo dnf -y --nogpgcheck --best --allowerasing install "$pkg".x86_64
            fi
        done
    fi

    set --
    if [ -z "$target" -o "$target" = m32 ]; then
        # try to install both 64 bit and 32 bit versions on 64 bit hosts (see below)
        if [ -n "$amd64" ]; then
            # this is sometimes necessary for rawhide
            set -- --exclude='glibc32*'
        fi
        for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel SFML-devel openal-soft-devel wxGTK-devel gtk3-devel; do
            case $pkg in
                *ffmpeg*)
                    [ -z "$ENABLE_FFMPEG" ] && continue
                    ;;
            esac

            pkg_arch=
            if [ -n "$amd64" ]; then
                pkg_arch=.x86_64

                if [ "$target" = m32 ]; then
                    pkg_arch=.i686
                fi
            fi

            # Check which is newer, wxGTK or wxGTK3.
            if [ "$pkg" = wxGTK-devel ]; then
                pkg=$(dnf -q --releasever=$(rpm -E %fedora) --showduplicates list wxGTK-devel wxGTK3-devel 2>/dev/null | awk '{ print $1 "\t" $2 }' | grep -Ev '^(Installed|Available)' | sort -rVu -k 2,2 | head -1 | awk '{ print $1 }' | sed -E 's/\.[^.]+//')

                [ -z "$pkg" ] && pkg=wxGTK3-devel
            fi

            set -- "$@" "${pkg}${pkg_arch}"
        done

        # fedora has a bug where all necessary -devel packages are not pulled in for 32 bit direct -devel deps
        # this hack adds them to the list
        if [ -n "$amd64" -a "$target" = m32 ]; then
            info_msg 'Calculating dependencies, this will take a while..'
            curdeps=
            newdeps=$@
            while [ "$curdeps" != "$newdeps" ]; do
                curdeps=$newdeps
                set -- $(echo "$@" $(sudo dnf -y --nogpgcheck repoquery --deplist "$@" 2>/dev/null | sed -n 's/\.x86_64$/.i686/; s/^ *provider: *\([^ ]*-devel-.*\)$/\1/p' | sort -u) | sed 's/  */\n/g' | sort -u)
                newdeps=$@
                printf '%s' .
            done

            echo
            info_msg 'Done'

            ## install the RPMs with rpm --force get around file conflicts

            host_rpms=$(echo "$@" | sed 's/\.i686//g')

            # first update the host arch versions to reduce chances of conflicts
            check sudo dnf -y --nogpgcheck --allowerasing --best install $host_rpms

            oldcwd=$PWD
            mkdir "$tmp/rpms"
            cd "$tmp/rpms"

            check sudo dnf -y --nogpgcheck --allowerasing --best download "$@"

            # first try installing with dnf to pull in deps
            check sudo dnf -y --nogpgcheck --allowerasing --best --skip-broken install *.rpm

            # follow up with rpm --force to ignore conflicts
            check sudo rpm -Uvh --force *.rpm

            rm -f *.rpm

            # reinstall the host rpms to make sure any overwritten files are the host version
            check sudo dnf -y --nogpgcheck --allowerasing --best download $host_rpms

            check sudo dnf -y --nogpgcheck --allowerasing --best --skip-broken install *.rpm

            check sudo rpm -Uvh --force *.rpm

            cd "$oldcwd"
            rm -rf "$tmp/rpms"

            ffmpeg=ffmpeg-devel.i686

            rpms_installed=1
        fi
    else # mingw build
        set -- "$@" pkgconfig
        case "$target" in
            mingw-w64-i686)
                target=mingw32
                cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-MinGW-w64-i686-static.cmake"
                ;;
            mingw-w64-x86_64)
                target=mingw64
                cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-MinGW-w64-x86_64-static.cmake"
                ;;
            *)
                error 'unknown cross target (this should not happen)'
                ;;
        esac
        # install static deps
        for pkg in zlib gettext SDL2 wxWidgets3 openal-soft; do
            set -- "$@" "${target}-${pkg}-static"
        done

        # get the necessary win32 headers
        git submodule update --init --remote --recursive

        warning='SFML is required for LINK support, Fedora does not currently have a MinGW SFML package, if you want LINK support you will need to install it manually'
    fi

    [ -z "$rpms_installed" ] && check sudo dnf -y --nogpgcheck --best --allowerasing install "$@"

    if [ -n "$ENABLE_FFMPEG" ] && ! rpm -q $ffmpeg >/dev/null 2>&1; then
        warning 'ffmpeg failed to install (probably due to conflicts)'
    fi

    [ -n "$warning" ] && warning "$warning"

    build_instructions
}

rhel_installdeps() {
    rhel=1
    ffmpeg=ffmpeg-devel
    rpms_installed=

    check_cross
    installing

    warning=

    rhel_release=$(rpm -E %rhel)
    tries=3
    curdir=$(pwd)

    # this source is necessary for mingw packages on rhel, and may be for other things in the future
    check sudo yum -y install epel-release

    # make sure rpmfusion is installed for ffmpeg
    if [ -n "$ENABLE_FFMPEG" ]; then
        while [ $tries -gt 0 ]; do
            mkdir -p "${tmp}/fusion"
            cd "${tmp}/fusion"
            if ! curl -fLO https://download1.rpmfusion.org/free/el/rpmfusion-free-release-${rhel_release}.noarch.rpm; then
                rhel_release=$((rhel_release - 1))
                tries=$((tries - 1))
                continue
            fi
            if ! curl -fLO https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-${rhel_release}.noarch.rpm; then
                tries=0
                break
            fi
            # check if already installed
            if rpm -q rpmfusion-free-release-${rhel_release} >/dev/null 2>&1 && rpm -q rpmfusion-nonfree-release-${rhel_release} >/dev/null 2>&1; then
                info_msg 'rpmfusion already installed, good'
                break
            fi
            # otherwise try to install
            if ! sudo rpm --nodeps -Uvh ./rpmfusion-*.rpm; then
                tries=0
                break
            fi
            break
        done
        cd "$curdir"
        if [ $tries -eq 0 ]; then
            warning 'installing rpmfusion repos failed, continuing without ffmpeg'
        fi
    fi

    # non-multiarch packages first
    CMAKE=cmake3
    check sudo yum -y install gcc gcc-c++ make cmake3 ccache git nasm redhat-rpm-config pkgconfig ccache ninja-build

    # try to install multiarch libgcc, glibc-devel and pkgconfig if available
    if [ -n "$amd64" ]; then
        for pkg in pkgconfig libgcc glibc-devel; do
            if [ "$target" = m32 ]; then
                sudo yum -y install "$pkg".i686
            else
                sudo yum -y install "$pkg".x86_64
            fi
        done
    fi

    set --
    if [ -z "$target" -o "$target" = m32 ]; then
        # try to install both 64 bit and 32 bit versions on 64 bit hosts (see below)
        if [ -n "$amd64" ]; then
            # this is sometimes necessary for rawhide
            set -- --exclude='glibc32*'
        fi

        warning='RHEL does not currently have SFML packages, LINK support will be disabled'

        for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel openal-soft-devel wxGTK3-devel gtk3-devel; do
            case $pkg in
                *ffmpeg*)
                    [ -z "$ENABLE_FFMPEG" ] && continue
                    ;;
            esac

            if [ -n "$amd64" ]; then
                if [ "$target" = m32 ]; then
                    set -- "$@" "${pkg}.i686"
                else
                    set -- "$@" "${pkg}.x86_64"
                fi
            else
                set -- "$@" "$pkg"
            fi
        done

        # redhat has a bug where all necessary -devel packages are not pulled in for 32 bit direct -devel deps
        # this hack adds them to the list
        if [ -n "$amd64" -a "$target" = m32 ]; then
            info_msg 'Calculating dependencies, this will take a while..'
            curdeps=
            newdeps=$@
            while [ "$curdeps" != "$newdeps" ]; do
                curdeps=$newdeps
                set -- $(echo "$@" $(repoquery --deplist "$@" 2>/dev/null | sed -n 's/\.x86_64$/.i686/; s/^ *provider: *\([^ ]*-devel-.*\)$/\1/p' | sort -u) | sed 's/  */\n/g' | sort -u)
                newdeps=$@
                printf '%s' .
            done

            echo
            info_msg 'Done'

            ## install the RPMs with rpm --force get around file conflicts

            host_rpms=$(echo "$@" | sed 's/\.i686//g')

            # first update the host arch versions to reduce chances of conflicts
            check sudo yum -y install $host_rpms

            oldcwd=$PWD
            mkdir "$tmp/rpms"
            cd "$tmp/rpms"

            check sudo yum -y download "$@"

            # first try installing with yum to pull in deps
            check sudo yum -y --skip-broken install *.rpm

            # follow up with rpm --force to ignore conflicts
            check sudo rpm -Uvh --force *.rpm

            rm -f *.rpm

            # reinstall the host rpms to make sure any overwritten files are the host version
            check sudo yum -y download $host_rpms

            check sudo yum -y --skip-broken install *.rpm

            check sudo rpm -Uvh --force *.rpm

            cd "$oldcwd"
            rm -rf "$tmp/rpms"

            ffmpeg=ffmpeg-devel.i686

            rpms_installed=1
        fi
    else # mingw build
        set -- "$@" pkgconfig
        case "$target" in
            mingw-w64-i686)
                target=mingw32
                cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-MinGW-w64-i686.cmake"
                ;;
            mingw-w64-x86_64)
                target=mingw64
                cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-MinGW-w64-x86_64.cmake"
                ;;
            *)
                error 'unknown cross target (this should not happen)'
                ;;
        esac
        # install static deps
        for pkg in zlib gettext SDL2 wxWidgets openal-soft; do
            set -- "$@" "${target}-${pkg}-static"
        done

        # get the necessary win32 headers
        git submodule update --init --remote --recursive

        warning='SFML is required for LINK support, RHEL/EPEL does not currently have a MinGW SFML package, if you want LINK support you will need to install it manually'
    fi

    [ -z "$rpms_installed" ] && check sudo yum -y install "$@"

    if [ -n "$ENABLE_FFMPEG" ] && ! rpm -q $ffmpeg >/dev/null 2>&1; then
        warning 'ffmpeg failed to install (probably due to conflicts)'
    fi

    [ -n "$warning" ] && warning "$warning"

    build_instructions
}

suse_installdeps() {
    suse=1
    check_cross
    installing

    tools="make cmake ccache nasm gettext-tools pkg-config ccache zip sfml2-devel ninja"

    libs="gcc gcc-c++ libSDL2-devel wxWidgets-3_0-devel openal-soft-devel" # ffmpeg-devel

    # ffmpeg requires packman repos

    if [ "$target" = m32 ]; then
        libs=$(echo "$libs" | sed -E 's/([^ ]) ([^ ])/\1-32bit \2/g; s/$/-32bit/;')
    fi

    check sudo zypper in -y $tools $libs

    build_instructions
}

nixos_installdeps() {
    nixos=1

    cat <<EOF

[32mTo build run:[0m

nix-shell --command 'mkdir build; cd build; $CMAKE .. $cmake_flags -G Ninja; ninja'

EOF
}

archlinux_require_yaourt() {
    if ! command -v yaourt >/dev/null; then
        (
            cd "$tmp"
            git clone https://aur.archlinux.org/package-query.git
            cd package-query
            makepkg --noconfirm -si
            cd ..
            git clone https://aur.archlinux.org/yaourt.git
            cd yaourt
            makepkg --noconfirm -si
        )
        [ $? -ne 0 ] && error 'could not install yaourt'
    fi
    pacman='yaourt --aur --m-arg=--skipinteg'
}

archlinux_installdeps() {
    arch_linux=1

    pacman='sudo pacman'
    command -v pacaur >/dev/null && pacman='pacaur --noedit'
    command -v yaourt >/dev/null && pacman='yaourt --aur --m-arg=--skipinteg'

    check_cross
    installing

    # check for gcc-multilib
    gcc_pkg=gcc
    if $pacman -Q gcc-multilib >/dev/null 2>&1; then
        gcc_pkg=gcc-multilib
    fi

    # update catalogs
    check $pacman -Sy

    # common needed dev packages
    # not using the base-devel group because it can break gcc-multilib
    check $pacman --noconfirm --needed -S binutils file grep gawk gzip libtool make patch sed util-linux nasm cmake ccache pkg-config git ccache zip ninja

    gtk=gtk3

    $pacman -Q gtk3-classic >/dev/null 2>&1 && gtk=gtk3-classic

    libs="zlib mesa gettext sdl2 wxgtk3 $gtk sfml openal"

    [ -n "$ENABLE_FFMPEG" ] && libs="$libs ffmpeg"

    if [ -z "$target" -o "$target" = m32 ]; then
        if [ -z "$target" -o -z "$amd64" ]; then
            # Native build.
            #
            # On newer versions wxgtk2 may have to be manually removed.
            if ! $pacman --noconfirm --needed -S "$gcc_pkg" $libs; then
                $pacman --noconfirm -R wxgtk2
            fi
            $pacman --noconfirm --needed -S "$gcc_pkg" $libs
        else
            # try to build 32 bit binaries

            # lib32-sfml and lib32-ffmpeg are in AUR
            archlinux_require_yaourt

            # enable multilib repos if not enabled
            cp /etc/pacman.conf ${tmp}/pacman.conf
            cat <<'EOF' >> ${tmp}/pacman.conf
[multilib-testing]
Include = /etc/pacman.d/mirrorlist
[multilib]
Include = /etc/pacman.d/mirrorlist
EOF
            pacman="$pacman --config ${tmp}/pacman.conf"

            # pull in multilib repo info
            $pacman -Sy

            yes | check $pacman --needed -S gcc-multilib

            libs32=
            for lib in $libs; do
                libs32="$libs32 lib32-$lib"
            done

            check $pacman --noconfirm --needed -S $libs32
        fi
    else
        # windows cross build
        case "$target" in
            *i686*)
                cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-MinGW-w64-i686.cmake"
                ;;
            *x86_64*)
                cmake_flags="$cmake_flags -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-MinGW-w64-x86_64.cmake"
                ;;
            *)
                # this will never be reached, it's checked in check_cross()
                error 'unknown cross target (you should not see this)'
                ;;
        esac

        check $pacman --noconfirm --needed -S "$gcc_pkg"

        archlinux_require_yaourt

        pkg_prefix='mingw-w64-'

        # cross toolchain (without headers and crt, we'll use -git versions)
        set --
        for p in binutils gcc winpthreads; do
            set -- "$@" "${pkg_prefix}${p}"
        done
        check $pacman --noconfirm --needed -S "$@"

        # build library deps from AUR

        info_msg 'We will now build dependencies from AUR, this will take quite a while and has a high probability of failure. In fact, it is definitely broken at the time of this writing. Press CTRL-C now to abort'

        countdown 16

        # pass appropriate make -jX flag through makepkg
        export MAKEPKG_CONF=${MAKEPKG_CONF:-/etc/makepkg.conf}

        grep -Ev '^[ 	]*MAKEFLAGS=' "$MAKEPKG_CONF" > "$tmp/makepkg.conf"

        export MAKEFLAGS=$(jobs_flag)
        echo "MAKEFLAGS=\"$MAKEFLAGS\"" >> "$tmp/makepkg.conf"

        export MAKEPKG_CONF="$tmp/makepkg.conf"

        # now do the AUR builds

        # first we need -headers-git and -crt-git (unless the non-git packages are installed)
        for p in "${pkg_prefix}headers" "${pkg_prefix}crt"; do
          if ! $pacman -Q "$p" >/dev/null 2>&1; then
              check $pacman --noconfirm --needed -S "${p}-git"
          else
              warning "${pkg_prefix}headers-git and ${pkg_prefix}crt-git are recommended over the regular versions, if you have build failures try to install them"
          fi
        done

        deps="zlib gettext pkg-config sdl2 wxmsw openal"

        # and the actual deps
        for p in $deps; do
            pkg="${pkg_prefix}${p}"
            # check if already installed
            if ! $pacman -Q "$pkg" >/dev/null 2>&1; then
                set -- "$@" "${pkg_prefix}${p}"
            fi
        done
        [ $# -gt 0 ] && check $pacman --noconfirm --needed -S "$@"

        # get the necessary win32 headers
        git submodule update --init --remote --recursive

        warning 'SFML is required for LINK support, the SFML package in AUR is currently broken, if you want LINK support you will need to install it manually'
    fi

    build_instructions
}

solus_installdeps() {
    solus=1

    check_cross
    installing

    check sudo eopkg -y update-repo
    check sudo eopkg -y install -c system.devel
    check sudo eopkg -y install git ccache ninja

    set -- sdl2-devel wxwidgets-devel libgtk-2-devel libgtk-3-devel libglu-devel openal-soft-devel

    if [ -n "$amd64" -a "$target" = m32 ]; then
        info_msg 'Calculating dependencies, this will take a while..'

        # first expand all dep lists recursively for -devel packages
        curdeps=
        newdeps=$@
        while [ "$curdeps" != "$newdeps" ]; do
            curdeps=$newdeps
            set -- $(echo "$@" $(sudo eopkg info "$@" 2>/dev/null | sed -n 's/^Dependencies  *:  *\(.*\)/\1/p' | sort -u) | sed 's/  */\n/g' | grep -- '-devel$' | sort -u)
            newdeps=$@
        done

        # transform to 32bit package names
        first=1
        for pkg in "$@"; do
            if [ "$first" = 1 ]; then
                set --
                first=0
            fi
            case "$pkg" in
                *-32bit-devel)
                    # already 32 bit
                    ;;
                *-devel)
                    set -- "$@" "${pkg%-devel}-32bit-devel"
                    ;;
                *)
                    set -- "$@" "$pkg"
                    ;;
            esac
        done

        # prune the ones that don't exist
        first=1
        for pkg in "$@"; do
            if [ "$first" = 1 ]; then
                set --
                first=0
            fi
            if ! sudo eopkg info "$pkg" | grep -q 'not found in binary repositories'; then
                set -- "$@" "$pkg"
            fi
        done
    else
        # no 32bit versions of these
        set -- "$@" SFML-devel ffmpeg-devel
    fi

    check sudo eopkg -y install "$@"

    if [ -n "$amd64" -a "$target" = m32 ]; then
        warning 'SFML is required for LINK support, there is no 32 bit SFML package in Solus currently, if you want LINK support you will need to install it manually'
        warning 'ffmpeg is required for game recording, there is no 32 bit ffmpeg package in Solus currently, you may wish to install it manually'
    fi

    build_instructions
}

gentoo_installdeps() {
    installing

    check sudo emerge-webrsync

    # We want the gtk3 slot for wxWidgets.
    wx_slot=$(equery -qC list -p -F '$slot' x11-libs/wxGTK | grep gtk3 | sort -rV | head -1)

    ebuilds="\
      sys-devel/gcc \
      dev-build/make \
      dev-build/cmake \
      dev-util/ccache \
      sys-devel/binutils \
      media-libs/libsdl2 \
      media-libs/libsfml \
      media-libs/openal \
      x11-libs/wxGTK:$wx_slot \
      sys-libs/zlib \
      dev-util/pkgconf \
      dev-lang/nasm \
      dev-build/ninja"

    [ -n "$ENABLE_FFMPEG" ] && ebuilds="$ebuilds media-video/ffmpeg"

    check sudo emerge -vna $ebuilds

    build_instructions
}

alpine_installdeps() {
    installing

    check sudo apk add cmake ninja g++ ccache nasm gettext-dev zlib-dev mesa-dev sdl2-dev glu-dev sfml-dev wxwidgets-dev gtk+3.0-dev zip

    build_instructions
}


windows_installdeps() {
    msys2=1

    check_cross
    installing

    # update catalogs
    check pacman -Sy

    pkgs=

    case "$target" in
        *clang*)
            pkgs="lldb clang"
            ;;
        *)
            pkgs="gcc gcc-libs gcc-libgfortran"
            ;;
    esac

    case "$target" in
        *i686*)
            pkgs="$pkgs nasm"
            ;;
        *)
            pkgs="$pkgs FAudio"
            ;;
    esac

    pkgs="$pkgs SDL2 sfml wxWidgets3.2 zlib binutils cmake crt-git headers-git make pkgconf tools-git windows-default-manifest libmangle-git ninja gdb ccache openal"

    case "$target" in
        *x86_64)
            pkgs="$pkgs extra-cmake-modules"
            ;;
    esac

    [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"

    set --
    for p in $pkgs; do
        set -- "$@" "${target}-${p}"
    done

    case "$target" in
        *clang*)
            # We use gcc windres for now, llvm-rc is sometimes broken.
            set -- "$@" mingw-w64-x86_64-binutils
        ;;
    esac

    # install
    check pacman --noconfirm --needed -S git make zip "$@"

    # get the necessary win32 headers
    check git submodule update --init --remote --recursive

    if [ "$MSYSTEM" = MSYS ]; then
        case "$target" in
            *i686)
                pre_build=\
"MSYSTEM=MINGW32 bash -l
cd $(pwd)"
                ;;
            *x86_64)
                pre_build=\
"MSYSTEM=MINGW64 bash -l
cd $(pwd)"
                ;;
        esac
        post_build=exit
    fi

    build_instructions
}

mac_installdeps() {
    if ! xcode-select -p >/dev/null 2>&1 && \
       ! pkgutil --pkg-info=com.apple.pkg.CLTools_Executables >/dev/null 2>&1 && \
       ! pkgutil --pkg-info=com.apple.pkg.DeveloperToolsCLI >/dev/null 2>&1; then

        error 'Please install XCode and the XCode Command Line Tools, then run this script again. On newer systems this can be done with: xcode-select --install   '
    fi

    if command -v brew >/dev/null; then
        brew_installdeps
    elif command -v port >/dev/null; then
        macports_installdeps
    elif command -v fink >/dev/null; then
        fink_installdeps
    else
        error 'You have no package manager, please install homebrew, macports or fink'
    fi
}

brew_installdeps() {
    check_cross
    installing

    check brew -v update

    brews="nasm cmake ccache gettext pkg-config sdl2 wxwidgets faudio ccache ninja zlib"

    [ -n "$ENABLE_FFMPEG" ] && brews="$brews ffmpeg"

    # sfml brew currently broken in the travis mac environment
#    if [ -z "$TRAVIS" ]; then
        brews="$brews sfml"
#    fi

    # This is necessary for the GitHub Actions CI:
    brew -v install python
    brew link --overwrite python

    check brew -v install -f $brews

    for brew in gettext wxwidgets; do
        brew unlink $brew
        brew link   $brew --force
    done

    brew -v cleanup

    build_instructions
}

macports_installdeps() {
    check_cross
    installing

    check sudo port -v selfupdate

    ports="cmake ccache nasm gettext pkgconfig libsdl2 sfml wxWidgets-3.0 libiconv ninja"

    [ -n "$ENABLE_FFMPEG" ] && ports="$ports ffmpeg"

    check sudo port -v install $ports
    check sudo port select wxWidgets wxWidgets-3.0

    build_instructions
}

fink_installdeps() {
    check_cross
    installing

    check sudo fink -vy selfupdate

    pkgs="cmake ccache nasm libgettext8-dev gettext-tools pkgconfig sdl2 wxwidgets300-osxcocoa libiconv-dev sfml24-dev ccache ninja"

    [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"

    check sudo fink -vy install $pkgs

    build_instructions
}

build_instructions() {
    cat <<EOF

[32mDone! To build do:[0m

$pre_build
mkdir build && cd build
$CMAKE .. -DCMAKE_BUILD_TYPE=Release $cmake_flags -G Ninja
ninja
$post_build

EOF
}

main "$@"

# vim:et sw=4:
