#!/usr/bin/env bash

# Exit on error
set -e

# change to the script directory
cd -- "$(dirname -- "${BASH_SOURCE[0]}")"

# initialization
PRODUCT="Zebra3"
if test -t 0 -a -t 1; then
    INTERACTIVE=1
else
    INTERACTIVE=0
fi
AS_ROOT=0
QUIET=0
REMOVE_OLD=0
VSTDIR="$HOME/.vst/u-he"
VST3DIR="$HOME/.vst3/u-he"
CLAPDIR="$HOME/.clap/u-he"
ARCH=$(uname -m)
NO_PRESETS=0

if [[ "$(uname -m)" = x86_64 ]]; then
    PLUGIN_BINARY="$PRODUCT/$PRODUCT.64.so"
else
    PLUGIN_BINARY="$PRODUCT/$PRODUCT.32.so"
fi
nm -D $PLUGIN_BINARY | grep -q VSTPluginMain && SUPPORT_VST2=1 || SUPPORT_VST2=0
nm -D $PLUGIN_BINARY | grep -q GetPluginFactory && SUPPORT_VST3=1 || SUPPORT_VST3=0
nm -D $PLUGIN_BINARY | grep -q clap_entry && SUPPORT_CLAP=1 || SUPPORT_CLAP=0

DIALOG=$PRODUCT/dialog

usage() {
    echo "usage: ./install.sh <options>..."
    echo -e "  --quiet            agree the license and install without asking questions"
    if [ "$SUPPORT_VST2" = "1" ]; then
        echo -e "  --vstdir=<path>    specify the VST directory. Default: $VSTDIR"
    fi
    if [ "$SUPPORT_VST3" = "1" ]; then
        echo -e "  --vst3dir=<path>   specify the VST3 directory. Default: $VST3DIR"
    fi
    if [ "$SUPPORT_CLAP" = "1" ]; then
        echo -e "  --clapdir=<path>   specify the CLAP directory. Default: $CLAPDIR"
    fi
    echo -e "  --as-root          lets you run this script as root. You have to know what you're doing."
    echo -e "  --remove-old       automatically remove old binaries and data directories without prompting"
    if test "$ARCH" = x86_64; then
        echo -e "  --without-32       do not install 32bit version"
    fi
    exit
}

# parse arguments
until test $# -eq 0; do
    case "$1" in
    --quiet)
        QUIET=1
        ;;
    --vstdir=*)
        VSTDIR=${1#--vstdir=}
        ;;
    --vst3dir=*)
        VST3DIR=${1#--vst3dir=}
        ;;
    --clapdir=*)
        CLAPDIR=${1#--clapdir=}
        ;;
    --help | -h)
        usage
        ;;
    --as-root)
        AS_ROOT=1
        ;;
    --no-presets)
        NO_PRESETS=1
        ;;
    --remove-old)
        REMOVE_OLD=1
        ;;
    *)
        echo wrong argument "$1"
        usage
        ;;
    esac
    shift
done

# prevent root install
if test "$(whoami)" = root -a "$AS_ROOT" -eq 0; then
    if test "$INTERACTIVE" -eq 1; then
        echo "Please do not install as root."
    else
        "$DIALOG" message 'Installation error' 'Please do not install as root.' OK
    fi
    exit 1
fi

if ! "$DIALOG" true; then
    if test $QUIET -eq 0; then
        if [[ "$(uname -m)" = x86_64 ]]; then
            DIALOG="$DIALOG.64"
        else
            DIALOG="$DIALOG.32"
        fi
        echo Please install missing libraries:
        ldd "$DIALOG"
    fi
    exit 1
fi

if test $QUIET -eq 0 -a -r "$PRODUCT/license.txt"; then
    if test $INTERACTIVE -eq 1; then
        cat "$PRODUCT/license.txt"
        echo
        echo --------------------------------------------
        echo
        while true; do
            echo -n "Do you agree the license's terms? [y/n] "
            read -r answer
            case "$answer" in
            y | Y | yes | YES | Yes) echo "" && break ;;
            n | N | no | NO | No) exit ;;
            esac
        done
    else
        answer=$("$DIALOG" license "$PRODUCT/license.txt")
        if test "$answer" != "yes"; then
            $DIALOG message "Installation aborted" "Installation aborted." OK
            exit
        fi
    fi
fi

# Helper function to remove items
remove_items() {
    local -n items_to_remove=$1
    for item in "${items_to_remove[@]}"; do
        $REMOVE_CMD "$item"
    done
}

# Helper function to ask user to and remove old files/directories.
# Will open a yes/no dialog window (GUI mode) or interactively ask the user to delete the files/directories from ITEMS_ARRAY_NAME.
# How to use: prompt_and_remove ITEMS_ARRAY_NAME "description" "dialog_title" "prompt_question" ["extra_message"]
# Parameters:
# ITEMS_ARRAY_NAME  - the array of the files/directories to be removed
# "description"     - Short summary of the files (will be placed in between a message consisting of "Found" and ":" before listing the files/directories)
# "dialog_title"    - window title of the dialog (in GUI mode)
# "prompt_question" - the question placed directly before the yes/no buttons (in GUI mode) or the text line when prompting the user for yes/no
# "[extra_message]  - optional message to placed before the prompt_question
prompt_and_remove() {
    local -n items=$1
    local description=$2
    local dialog_title=$3
    local prompt_question=$4
    local extra_message=$5
    
    if [ ${#items[@]} -eq 0 ]; then
        return
    fi
    
    if test $REMOVE_OLD -eq 1; then
        remove_items items
    elif test $INTERACTIVE -eq 1; then
        echo "Found ${description}:"
        for item in "${items[@]}"; do
            echo "  - $item"
        done
        echo
        if [ -n "$extra_message" ]; then
            echo "$extra_message"
        fi
        while true; do
            echo -n "${prompt_question} [y/n] "
            read -r answer
            case "$answer" in
            y | Y | yes | YES | Yes)
                remove_items items
                echo "Old items removed."
                break
                ;;
            n | N | no | NO | No)
                echo "Keeping old items."
                break
                ;;
            esac
        done
    else
        ITEM_LIST=""
        for item in "${items[@]}"; do
            ITEM_LIST="${ITEM_LIST}${item}
"
        done
        MSG="Found ${description}:
${ITEM_LIST}"
        if [ -n "$extra_message" ]; then
            MSG="${MSG}
${extra_message}
"
        fi
        MSG="${MSG}
${prompt_question}"
        answer=$($DIALOG message "$dialog_title" "$MSG" "Yes" "No" | tr -d '\0')
        if test "$answer" = "Yes"; then
            remove_items items
        fi
    fi
}

# cleanup old installations with architecture suffixes and old data directories
if test $QUIET -eq 0 || test $REMOVE_OLD -eq 1; then
    OLD_FILES=()
    if [ "$SUPPORT_VST2" = "1" ]; then
        [ -e "$VSTDIR/$PRODUCT.64.so" ] && OLD_FILES+=("$VSTDIR/$PRODUCT.64.so")
        [ -e "$VSTDIR/$PRODUCT.32.so" ] && OLD_FILES+=("$VSTDIR/$PRODUCT.32.so")
    fi
    if [ "$SUPPORT_CLAP" = "1" ]; then
        [ -e "$CLAPDIR/$PRODUCT.64.clap" ] && OLD_FILES+=("$CLAPDIR/$PRODUCT.64.clap")
        [ -e "$CLAPDIR/$PRODUCT.32.clap" ] && OLD_FILES+=("$CLAPDIR/$PRODUCT.32.clap")
    fi
    [ -e "$HOME/.u-he/$PRODUCT/$PRODUCT.64.avx.so" ] && OLD_FILES+=("$HOME/.u-he/$PRODUCT/$PRODUCT.64.avx.so")

    # Check for old data directories
    OLD_DIRS=()
#    DATA_DIRS=("Data/Fonts" "Data/Images" "Data/Locale" "Data/Scripts" "Modal Profiles/Factory" "Modules" "Presets" "Tunefiles")
#    DATA_DIRS=("Data/Fonts" "Data/Images" "Data/Locale" "Data/Scripts" "Modal Profiles/Factory" "Presets" )
    DATA_DIRS=("Data/Fonts" "Data/Images" "Data/Locale" "Data/Scripts" "Modal Profiles/Factory" )
    for dir in "${DATA_DIRS[@]}"; do
        [ -d "$HOME/.u-he/$PRODUCT/$dir" ] && OLD_DIRS+=("$HOME/.u-he/$PRODUCT/$dir")
    done

    # Prefer removal using gio, fallback using rm
    if command -v gio &> /dev/null; then
        REMOVE_CMD="gio trash"
    else
        REMOVE_CMD="rm -rf"
    fi

    # Cleanup old binary names
    prompt_and_remove OLD_FILES \
        "old architecture-suffixed binaries from previous installation" \
        "Old installation files found" \
        "Remove these old files?"

    # Cleanup old data directories
    prompt_and_remove OLD_DIRS \
        "factory data directories from previous installation" \
        "Old factory data directories found" \
        "Remove these directories?" \
        "It's highly recommended to remove these directories before installation."
fi

# copy new data

# presets
if test "$NO_PRESETS" -eq 1; then
    find "$PRODUCT/Presets/$PRODUCT/" \
        \( -type f -a -iname '*.h2p' -a -not -iname 'initialize.h2p' -a -delete \) \
        -o \( -empty -a -delete \)
fi

mkdir -p "$HOME/.u-he/"
cp -R "$PRODUCT" "$HOME/.u-he/"
# cp LinuxChangeLog.txt "$HOME/.u-he/$PRODUCT/"

# symlink VST and VST3
if [ "$SUPPORT_VST2" = "1" ]; then
    mkdir -p "$VSTDIR"
fi
if [ "$SUPPORT_VST3" = "1" ]; then
    mkdir -p "$VST3DIR/$PRODUCT.vst3/Contents/x86_64-linux/"
    mkdir -p "$VST3DIR/$PRODUCT.vst3/Contents/i686-linux/"
    mkdir -p "$VST3DIR/$PRODUCT.vst3/Contents/Resources/Documentation/"
fi
if [ "$SUPPORT_CLAP" = "1" ]; then
    mkdir -p "$CLAPDIR"
fi

ln -sf "$HOME/.u-he/$PRODUCT/"*.pdf "$VST3DIR/$PRODUCT.vst3/Contents/Resources/Documentation/"

if [ "$(uname -m)" = x86_64 ]; then
    if [ "$SUPPORT_VST2" = "1" ]; then
        ln -sf "$HOME/.u-he/$PRODUCT/$PRODUCT.64.so" "$VSTDIR/$PRODUCT.so"
    fi
    if [ "$SUPPORT_VST3" = "1" ]; then
        ln -sf "$HOME/.u-he/$PRODUCT/$PRODUCT.64.so" "$VST3DIR/$PRODUCT.vst3/Contents/x86_64-linux/$PRODUCT.so"
    fi
    if [ "$SUPPORT_CLAP" = "1" ]; then
        ln -sf "$HOME/.u-he/$PRODUCT/$PRODUCT.64.so" "$CLAPDIR/$PRODUCT.clap"
    fi
else
    if [ "$SUPPORT_VST2" = "1" ]; then
        ln -sf "$HOME/.u-he/$PRODUCT/$PRODUCT.32.so" "$VSTDIR/$PRODUCT.so"
    fi
    if [ "$SUPPORT_VST3" = "1" ]; then
        ln -sf "$HOME/.u-he/$PRODUCT/$PRODUCT.32.so" "$VST3DIR/$PRODUCT.vst3/Contents/i686-linux/$PRODUCT.so"
    fi
    if [ "$SUPPORT_CLAP" = "1" ]; then
      ln -sf "$HOME/.u-he/$PRODUCT/$PRODUCT.32.so" "$CLAPDIR/$PRODUCT.clap"
    fi
fi

if test "$PRODUCT" = "ZebraHZ"; then
    ln -snf "$HOME/.u-he/Zebra2/Presets/Zebra2" "$HOME/.u-he/ZebraHZ/Presets/ZebraHZ/Zebra2"
fi

cat <<EOF >"$HOME/.u-he/$PRODUCT/README-Linux.txt"
Dependencies
------------

You need xdg-open and trash-put to be in /usr/bin/.

Keyboard Modifiers
------------------

In certain cases, Alt+click will not be available to the plugin.
If you notice this happening, please try AtlGr+click instead.

How to uninstall
----------------

To uninstall simply remove the following files/folders:
$HOME/.u-he/$PRODUCT
EOF

if [ "$SUPPORT_VST2" = "1" ]; then
    echo "\$VSTDIR/\$PRODUCT.so" >> "$HOME/.u-he/$PRODUCT/README-Linux.txt"
fi

if [ "$SUPPORT_VST3" = "1" ]; then
    echo "\$VST3DIR/\$PRODUCT.vst3" >> "$HOME/.u-he/$PRODUCT/README-Linux.txt"

fi

if [ "$SUPPORT_CLAP" = "1" ]; then
    echo "\$CLAPDIR/\$PRODUCT.clap" >> "$HOME/.u-he/$PRODUCT/README-Linux.txt"
fi

cat <<EOF >>"$HOME/.u-he/$PRODUCT/README-Linux.txt"
Be sure to back up all your presets before removing any files!

Extra configuration
-------------------

# configure the realtime priority of the thread pool using the following environment variable:
export UHE_RT_PRIO=64

Troubleshooting
---------------

If you have an issue maybe your solution is somewhere on KVR:
https://www.kvraudio.com/forum/viewtopic.php?f=31&t=424953

 - Menu and dialogs are not shown
   -> Known issue under Gnome / Wayland
   -> Known issue under the MIR display server
   -> Try exporting GDK_BACKEND=x11, see https://www.kvraudio.com/forum/viewtopic.php?p=6998254#p6998254
EOF

if test $QUIET -eq 0; then
    if test $INTERACTIVE -eq 0; then
        $DIALOG message "Installation succeed" "Installation succeed." OK
    else
        cat <<EOF

${PRODUCT}'s data was installed to ${HOME}/.u-he/${PRODUCT}
EOF

if [ "$SUPPORT_CLAP" = "1" ]; then
  echo "The CLAP has been installed in: ${CLAPDIR}"
fi

if [ "$SUPPORT_VST3" = "1" ]; then
  echo "The VST3 has been installed in: ${VST3DIR}/${PRODUCT}.vst3"
fi


if [ "$SUPPORT_VST2" = "1" ]; then
    echo "The VST has been installed in: ${VSTDIR}"
fi

cat <<EOF

Have fun with ${PRODUCT} and thank you for installing u-he software!
EOF
    fi
fi
