#!/usr/bin/env bash
set -eu

cat <<"EOF"
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⣶⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⠿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⠀⢀⣠⣴⣶⣿⣿⣿⣿⣿⣿⣿⣶⣦⣄⡀⠀⠀⠀⠀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⡆⠀⢀⣴⣿⣿⣿⣿⠿⠟⠛⠛⠛⠻⠿⣿⣿⣿⣿⣦⡀⠀⢰⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⠟⠉⠀⣴⣿⣿⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⣿⣿⣿⣦⠀⠉⠻⢿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⡿⠋⠀⠀⠀⣼⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣧⠀⠀⠀⠙⢿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⡿⠉⠀⠀⠀⠀⢰⣿⣿⣿⠁⠀⠀⠀⠀⣤⣾⣿⣿⣿⣷⣦⠀⠀⠀⠀⠈⣿⣿⣿⡆⠀⠀⠀⠀⠈⠻⣿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⡿⡏⠀⠀⠀⠀⠀⠀⣼⣿⣿⡏⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⢸⣿⣿⣷⠀⠀⠀⠀⠀⠀⢹⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⢿⣿⣿⡇⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⢸⣿⣿⣿⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣷⡄⠀⠀⠀⠀⠀⢸⣿⣿⣷⠀⠀⠀⠀⠘⢿⣿⣿⣿⣿⣿⡿⠃⠀⠀⠀⠀⣼⣿⣿⡏⠀⠀⠀⠀⠀⢀⣾⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⣦⣄⠀⠀⠀⠀⢿⣿⣿⣇⠀⠀⠀⠀⠀⠉⠛⠛⠛⠉⠀⠀⠀⠀⠀⣸⣿⣿⣿⠁⠀⠀⠀⣠⣴⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⣷⣤⡀⠀⠘⢿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⡿⠃⠀⢀⣠⣾⣿⣿⠿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⡀⠈⠻⢿⣿⣿⣶⠀⠀⠻⣿⣿⣿⣷⣦⣄⠀⠀⠀⠀⠀⣠⣤⣾⣿⣿⡿⠏⠁⠀⣴⣿⣿⣿⠟⠉⢀⣤⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢿⢿⠇⠀⠀⠀⠉⠛⠛⠀⠀⠀⠈⠙⠿⣿⣿⣿⣷⠀⠀⠀⣾⣿⣿⣿⠿⠁⠀⠀⠀⠀⠙⠛⠋⠀⠀⠀⠸⣿⣿⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⠀⠀⠀⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⠀⠀⠀⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⠀⠀⠀⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣵⣷⣄⠀⠀⠀⠀⠀⢀⣿⣿⣿⠀⠀⠀⣿⣿⣿⡄⠀⠀⠀⠀⠀⣠⣾⣷⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣿⣿⣷⣦⣄⣀⣤⣾⣿⡿⠋⠀⠀⠀⠘⣿⣿⣷⣤⣀⣠⣤⣾⣿⡿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠻⠿⣿⣿⡟⠛⠁⠀⠀⠀⠀⠀⠀⠈⠘⠿⢿⣿⣿⠻⠏⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
EOF

SCRIPT_DIR="$(dirname "$(realpath "$0")")"
cd "$SCRIPT_DIR"
INSTALL_DESTINATION="$HOME/.local/share/ACCELA"
INSTALL_DESTINATION_SOURCE_OLD="$INSTALL_DESTINATION/bin"
INSTALL_DESTINATION_SOURCE="$INSTALL_DESTINATION/src"
SOURCE="$SCRIPT_DIR/bin"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Check if notify-send exists globally
command -v notify-send &> /dev/null
NOTIFY_SEND_AVAILABLE=$?

# Logging functions
log_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
    set +eu
    if [ "$NOTIFY_SEND_AVAILABLE" -eq 0 ]; then
        notify-send -t 5000 "INFO" "$1" 2>/dev/null
    fi
    set -eu
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
    set +eu
    if [ "$NOTIFY_SEND_AVAILABLE" -eq 0 ]; then
        notify-send -t 5000 -u normal "WARNING" "$1" 2>/dev/null
    fi
    set -eu
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
    set +eu
    if [ "$NOTIFY_SEND_AVAILABLE" -eq 0 ]; then
        notify-send -t 10000 -u critical "ERROR" "$1" 2>/dev/null
    fi
    set -eu
}

# Function to detect installation type
detect_install_type() {
    if [ -f "$SOURCE/run.sh" ] && [ -d "$SOURCE/src" ] && [ -f "$SOURCE/requirements.txt" ]; then
        echo "source"
    elif [ -f "$SOURCE/ACCELA" ] && [ -f "$SOURCE/accela.png" ]; then
        echo "binary"
    elif [ -f "$SOURCE/ACCELA.AppImage" ] && [ -f "$SOURCE/accela.png" ]; then
        echo "appimage"
    else
        echo "unknown"
    fi
}

# Function to clean up existing installation
cleanup_existing() {
    log_info "Removing existing installation..."
    
    # Remove old installation directories
    if [[ -d "$INSTALL_DESTINATION_SOURCE" ]] || [[ -f "$INSTALL_DESTINATION/run.sh" ]] || [[ -d "$INSTALL_DESTINATION/.venv" ]]; then
        rm -rf "$INSTALL_DESTINATION_SOURCE" 2>/dev/null
        rm -rf "$INSTALL_DESTINATION/run.sh" 2>/dev/null
    fi
    
    # Remove old installation directory if it exists
    if [ -d "$INSTALL_DESTINATION_SOURCE_OLD" ]; then
        rm -rf "$INSTALL_DESTINATION_SOURCE_OLD"
    fi
    
    # Remove existing ACCELA binary/AppImage if it exists
    if [ -f "$HOME/.local/share/ACCELA/ACCELA" ]; then
        rm -f "$HOME/.local/share/ACCELA/ACCELA"
    fi
    if [ -f "$HOME/.local/share/ACCELA/ACCELA.AppImage" ]; then
        rm -f "$HOME/.local/share/ACCELA/ACCELA.AppImage"
    fi
}

# Function to install icon and desktop entry
install_desktop_entry() {
    local exec_path="$1"
    
    # Copy icon if it exists
    if [ -f "$SOURCE/accela.png" ]; then
        ICON_THEME_DIR="$HOME/.local/share/icons/hicolor/256x256/apps"
        mkdir -p "$ICON_THEME_DIR"
        cp -rpf "$SOURCE/accela.png" "$ICON_THEME_DIR/accela.png"
        #log_info "Installed Icon"
    fi
    
    # Create desktop entry
    DESKTOP_ENTRY_DIR="$HOME/.local/share/applications"
    mkdir -p "$DESKTOP_ENTRY_DIR"
    
    cat >"$DESKTOP_ENTRY_DIR/accela.desktop" <<EOL
[Desktop Entry]
Version=2.0
Name=ACCELA
Comment=ＧｏＤ_Ｉｓ_ｉＮ_ｔＨｅ_ＷｉＲｅＤ
Exec=$exec_path %u
Icon=accela
Terminal=false
Type=Application
Categories=Utility;Application;
MimeType=x-scheme-handler/accela;
EOL
    log_info "Added ACCELA to programs"
    
    # Update icon cache and desktop database
    # Skip GTK icon cache on KDE since it hangs
    if [ -z "${XDG_CURRENT_DESKTOP:-}" ] || [[ "$XDG_CURRENT_DESKTOP" != *"KDE"* ]]; then
        command -v gtk-update-icon-cache &>/dev/null && gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" 2>/dev/null || true
        command -v gtk4-update-icon-cache &>/dev/null && gtk4-update-icon-cache "$HOME/.local/share/icons/hicolor" 2>/dev/null || true
    fi
    
    if command -v update-desktop-database &>/dev/null; then
        update-desktop-database "$DESKTOP_ENTRY_DIR" 2> /dev/null
    fi

    # Register URL scheme handler
    if command -v xdg-mime &>/dev/null; then
        xdg-mime default accela.desktop x-scheme-handler/accela
        log_info "Registered accela:// URL scheme handler"
    fi
}

# Function to install CLI wrapper in ~/.local/bin
install_cli_wrapper() {
    local bin_dir="$HOME/.local/bin"
    local wrapper_path="$bin_dir/accela"

    mkdir -p "$bin_dir"

    cat >"$wrapper_path" <<'EOL'
#!/usr/bin/env bash
set -eu

INSTALL_DIR="$HOME/.local/share/ACCELA"
APPIMAGE="$INSTALL_DIR/ACCELA.AppImage"
RUNSH="$INSTALL_DIR/run.sh"
BIN="$INSTALL_DIR/ACCELA"

if [ -x "$APPIMAGE" ]; then
    exec "$APPIMAGE" "$@"
elif [ -x "$RUNSH" ]; then
    exec "$RUNSH" "$@"
elif [ -x "$BIN" ]; then
    exec "$BIN" "$@"
else
    echo "ACCELA not found in $INSTALL_DIR" >&2
    exit 1
fi
EOL

    chmod +x "$wrapper_path"

    if ! echo ":${PATH}:" | grep -q ":${bin_dir}:"; then
        log_warn "${bin_dir} is not in PATH. Add it to run 'accela' from the terminal."
    fi
}

venv() {
    python3 -m venv .venv
    source .venv/bin/activate
    pip install -r requirements.txt
    deactivate
}

# Function to install from source
install_source() {
    log_info "Installing ACCELA source..."

    # Check if source directory exists and has the required files
    if [ ! -f "$SOURCE/run.sh" ]; then
        log_error "Error: run.sh not found in $SOURCE"
        exit 1
    fi
    
    if [ ! -d "$SOURCE/src" ]; then
        log_error "Error: src directory not found in $SOURCE"
        exit 1
    fi
    
    # Install source files
    mkdir -p "$INSTALL_DESTINATION"
    #log_info "Copying source files to $INSTALL_DESTINATION..."
    cp -rpf "$SOURCE/src" "$INSTALL_DESTINATION_SOURCE/"
    cp -rpf "$SOURCE/requirements.txt" "$INSTALL_DESTINATION/"
    cp -rpf "$SOURCE/run.sh" "$INSTALL_DESTINATION/"
    chmod +x "$INSTALL_DESTINATION/run.sh"
    chmod +x "$INSTALL_DESTINATION_SOURCE/deps/DepotDownloaderMod" 2>/dev/null || true
    #log_info "Installed source files and run.sh"
    
    # Set up virtual environment at the installation destination
    cd "$INSTALL_DESTINATION"
    
    # Check if Python 3 is available
    if ! command -v python3 &>/dev/null; then
        log_error "Error: python3 not found, Please install python."
        exit 1
    fi
    
    log_info "Setting up requirements and checking dependencies"
    
    if [ "${SKIPVENV:-}" != "1" ]; then
        venv
    else
        if [ ! -f ".venv/bin/activate" ]; then
            venv
        fi
    fi

    # Install desktop entry
    install_desktop_entry "$INSTALL_DESTINATION/run.sh"

    # Install CLI wrapper
    install_cli_wrapper
}

# Function to install from binary
install_binary() {
    log_info "Installing ACCELA binary..."
        rm -rf "$INSTALL_DESTINATION/.venv" 2>/dev/null

    # Check if binary exists
    if [ ! -f "$SOURCE/ACCELA" ]; then
        log_error "Error: ACCELA binary not found in $SOURCE"
        exit 1
    fi
    
    if [ ! -f "$SOURCE/accela.png" ]; then
        log_error "Error: accela.png not found in $SOURCE"
        exit 1
    fi
    
    mkdir -p "$INSTALL_DESTINATION"
    cp -rpf "$SOURCE/ACCELA" "$INSTALL_DESTINATION/ACCELA"
    chmod +x "$INSTALL_DESTINATION/ACCELA"
    
    # Install desktop entry
    install_desktop_entry "$INSTALL_DESTINATION/ACCELA"

    # Install CLI wrapper
    install_cli_wrapper
}

# Function to install from AppImage
install_appimage() {
    log_info "Installing ACCELA AppImage..."
    rm -rf "$INSTALL_DESTINATION/.venv" 2>/dev/null

    # Check if AppImage exists
    if [ ! -f "$SOURCE/ACCELA.AppImage" ]; then
        log_error "Error: ACCELA.AppImage not found in $SOURCE"
        exit 1
    fi
    
    if [ ! -f "$SOURCE/accela.png" ]; then
        log_error "Error: accela.png not found in $SOURCE"
        exit 1
    fi
    
    mkdir -p "$INSTALL_DESTINATION"
    cp -rpf "$SOURCE/ACCELA.AppImage" "$INSTALL_DESTINATION/ACCELA.AppImage"
    chmod +x "$INSTALL_DESTINATION/ACCELA.AppImage"
    
    # Install desktop entry
    install_desktop_entry "$INSTALL_DESTINATION/ACCELA.AppImage"

    # Install CLI wrapper
    install_cli_wrapper
}

installed_message() {
    msglaunch="Run by launching ACCELA from your applications menu"
    echo -e "${GREEN}[INFO]${NC} ACCELA has been installed to $INSTALL_DESTINATION"
    echo -e "${GREEN}[INFO]${NC} $msglaunch"
    (
        sleep 5
        set +eu
        if [ "$NOTIFY_SEND_AVAILABLE" -eq 0 ]; then
            notify-send -t 10000 "INFO" "ACCELA has been installed to\n$INSTALL_DESTINATION" 2>/dev/null
        fi
        sleep 7
        if [ "$NOTIFY_SEND_AVAILABLE" -eq 0 ]; then
            notify-send -t 10000 "INFO" "$msglaunch" 2>/dev/null
        fi
        set -eu
    ) & disown
}

# Main installation logic
INSTALL_TYPE=$(detect_install_type)

#log_info "Detected installation type: $INSTALL_TYPE"

# Clean up existing installation
cleanup_existing

# Switch case for installation type
case "$INSTALL_TYPE" in
    "source")
        install_source
        installed_message
        ;;
    "binary")
        install_binary
        installed_message
        ;;
    "appimage")
        install_appimage
        installed_message
        ;;
    "unknown")
        log_error "Unable to detect installation type. Please ensure the current directory contains either AppImage, the binary or bin folder"
        exit 1
        ;;
    *)
        log_error "Unknown installation type: $INSTALL_TYPE"
        exit 1
        ;;
esac
