#!/usr/bin/env bash

# Cursor firejailed AppImage Install/Update Script
# This script download and installs (or upgrades) the latest version of Cursor with a corresponding firejail config.
# v1.0.0

set -euo pipefail  # Exit on any error

# Configuration
CURSOR_APPIMAGE="$HOME/.local/bin/Cursor.AppImage"
SANDBOX_ROOT="$HOME/cursoride"

# Inlined utility: Pretty logging

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

print_status() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARN]${NC} $1" 1>&2
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1" 1>&2
}

# Inlined utility: Self-cleaning temp files and dirs

gcHeap=()
cleanup() {
  for gcPath in "${gcHeap[@]}"; do
    rm -rf "$gcPath"
  done
}
trap cleanup EXIT

temp_dir() {
  local newDir
  newDir=$(mktemp -d)
  gcHeap+=(newDir)
  echo "$newDir"
}

temp_file() {
  local newFile
  newFile=$(mktemp)
  gcHeap+=(newFile)
  echo "$newFile"
}

# Start of actual application

detect_platform() {
    local arch platform
    arch=$(uname -m)
    case "$arch" in
        "x86_64")
            platform="linux-x64"
            ;;
        "aarch64"|"arm64")
            platform="linux-arm64"
            ;;
        *)
            print_error "Unsupported architecture: $arch"
            print_error "Supported platforms: linux-x64, linux-arm64"
            exit 1
            ;;
    esac
    echo "$platform"
}

check_dependencies() {
    for cmd in curl jq firejail; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            print_error "Missing required dependency: $cmd"
            print_error ""
            print_error "Please install $cmd and try again."
            print_error "On Ubuntu/Debian: sudo apt install $cmd"
            print_error "On CentOS/RHEL: sudo dnf install $cmd"
            print_error "On Arch: sudo pacman -S $cmd"
            exit 1
        fi
    done
}

extract_appimage() {
    local appImage="$1"
    pushd "$(temp_dir)" 1>/dev/null
    if ! "$appImage" --appimage-extract >/dev/null; then
        print_error "Failed to extract AppImage, cannot determine installed version"
        print_error "This may indicate a corrupted or invalid AppImage"
        exit 1
    fi
    echo "$(pwd)/squashfs-root"
    popd >/dev/null
}

extract_version() {
    pushd "$(extract_appimage "$1")" >/dev/null
    jq '.version' <"usr/share/cursor/resources/app/product.json"
    popd >/dev/null
}

install_icons() {
    local appImagePath="$1" iconDir="$2"
    pushd "$(extract_appimage "$appImagePath")" >/dev/null
    mkdir -p "$iconDir"
    cp -r usr/share/icons/* "$iconDir"
    popd >/dev/null
}

install_profile_if_absent() {
  local profilePath="$1"
  [ ! -f "$profilePath" ] || return
  mkdir -p "$(dirname "$profilePath")"
  cat >"$profilePath" <<EOF
caps.drop all
nonewprivs
noroot
protocol unix,inet,inet6,netlink

private $SANDBOX_ROOT

include electron.profile
EOF
}

install_desktop_file() {
    local appImagePath="$1" desktopFilePath="$2"
    mkdir -p "$(dirname "$desktopFilePath")"
    cat >"$desktopFilePath" <<EOF
[Desktop Entry]
Name=Cursor (firejail)
Comment=The AI Code Editor.
Exec=firejail --appimage --profile=cursor $appImagePath %F
Icon=cursor
GenericName=Text Editor
Type=Application
StartupNotify=false
StartupWMClass=Cursor
Categories=TextEditor;Development;IDE;
MimeType=application/x-cursor-workspace;
Actions=new-empty-window;
Keywords=cursor;

[Desktop Action new-empty-window]
Name=New Empty Window
Name[de]=Neues leeres Fenster
Name[es]=Nueva ventana vacía
Name[fr]=Nouvelle fenêtre vide
Name[it]=Nuova finestra vuota
Name[ja]=新しい空のウィンドウ
Name[ko]=새 빈 창
Name[ru]=Новое пустое окно
Name[zh_CN]=新建空窗口
Name[zh_TW]=開新空視窗
Exec=firejail --appimage --profile=cursor $appImagePath %F
Icon=cursor
EOF
}

# Main execution
main() {
    local platform newVersion installedVersion appImageUrl tempDownloadMetadata tempAppImage
    print_status "Starting Cursor AppImage update process..."

    check_dependencies
    print_status "All required dependencies are available"

    platform=$(detect_platform)
    print_status "Detected platform: $platform"

    local metadataUrl="https://cursor.com/api/download?platform=$platform&releaseTrack=stable"
    print_status "Downloading latest metadata from $metadataUrl"
    tempDownloadMetadata=$(temp_file)
    if ! curl -SL "$metadataUrl" -o "$tempDownloadMetadata"; then
        print_warning "This script depends on an undocumented API to identify updates and the latest download URL"
        print_error "Failed to download metadata for latest Cursor download at $metadataUrl"
        exit 1
    fi
    print_status "Metadata downloaded successfully"

    if [ ! -f "$CURSOR_APPIMAGE" ]; then
      print_status "No existing application found at $CURSOR_APPIMAGE, installation will commence"
    else
      newVersion=$(jq '.version' <"$tempDownloadMetadata")
      installedVersion=$(extract_version "$CURSOR_APPIMAGE")
      if [ "$installedVersion" = "$newVersion" ]; then
        print_status "No update needed - newVersion $newVersion is already installed"
        exit 0
      fi
      print_status "Current version $installedVersion != $newVersion, upgrade will commence"
    fi

    appImageUrl=$(jq -r '.downloadUrl' <"$tempDownloadMetadata")
    print_status "Downloading $appImageUrl ..."
    tempAppImage=$(temp_file)
    if ! curl -SL "$appImageUrl" -o "$tempAppImage"; then
        print_error "Failed to download AppImage"
        exit 1
    fi

    install -D "$tempAppImage" "$CURSOR_APPIMAGE"
    print_status "AppImage installed as $CURSOR_APPIMAGE"

    install_icons "$CURSOR_APPIMAGE" "$XDG_DATA_HOME/icons/"
    print_status "Icons from $CURSOR_APPIMAGE installed into $XDG_DATA_HOME/icons/"

    if [ -d "$SANDBOX_ROOT" ]; then
      print_status "$SANDBOX_ROOT already exists and will be used as the sandbox root"
    else
      mkdir -p "$SANDBOX_ROOT"
      print_status "$SANDBOX_ROOT has been created and will be used as sandbox root"
    fi

    install_profile_if_absent "$XDG_CONFIG_HOME/firejail/cursor.profile"
    print_status "Cursor firebase profile installed at $XDG_CONFIG_HOME/firejail/cursor.profile"

    install_desktop_file "$CURSOR_APPIMAGE" "$XDG_DATA_HOME/applications/cursor-sandbox"
    print_status "Desktop file written to $XDG_DATA_HOME/applications/cursor-sandbox"

    print_status "Cursor AppImage update completed successfully!"
}

main "$@"
