#!/bin/dash
# java-version-manager.sh
# POSIX script to manage multiple OpenJDK versions using symbolic links
# Inspired by archlinux-java

# Base directory for JVMs
JVM_DIR="/usr/lib/jvm"
DEFAULT_NAME="default"
DEFAULT_PATH="${JVM_DIR}/${DEFAULT_NAME}"

# System configuration for PATH
SYSTEM_PROFILE_DIR="/etc/profile.d"
JAVA_CONFIG_FILE="${SYSTEM_PROFILE_DIR}/java-default.sh"

# Colors for output (optional, POSIX compatible)
if [ -t 1 ]; then
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[1;33m'
    BLUE='\033[0;34m'
    BOLD='\033[1m'
    NC='\033[0m' # No Color
else
    RED=''
    GREEN=''
    YELLOW=''
    BLUE=''
    BOLD=''
    NC=''
fi

# Check if running as root
check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        printf "${RED}Error: This command requires root privileges${NC}\n"
        printf "${YELLOW}Run with doas or sudo:${NC}\n"
        printf "    doas %s %s\n" "$(basename "$0")" "$*"
        exit 1
    fi
}

# Get current default Java
get_default_java() {
    if [ -L "${DEFAULT_PATH}" ]; then
        path=$(readlink -f "${DEFAULT_PATH}" 2>/dev/null)
        if [ -n "$path" ] && [ "$path" != "/dev/null" ]; then
            basename "$path"
        else
            echo ""
        fi
    else
        echo ""
    fi
}

# Get list of installed Java environments
get_installed_javas() {
    javas=""
    if [ -d "${JVM_DIR}" ]; then
        for dir in "${JVM_DIR}"/java-*-openjdk*; do
            if [ -d "$dir" ] && [ -x "$dir/bin/java" ]; then
                javas="${javas} $(basename "$dir")"
            fi
        done
    fi
    echo "$javas"
}

# Check if Java environment is valid
# $1: Java environment name
is_java_valid() {
    [ "$1" != "${DEFAULT_NAME}" ] && [ -x "${JVM_DIR}/$1/bin/java" ]
}

# Set symbolic link to Java environment
# $1: Java environment name
set_default_link() {
    new_default="$1"
    
    # Remove old link
    rm -f "${DEFAULT_PATH}" 2>/dev/null
    
    # Create new link
    ln -sf "${JVM_DIR}/${new_default}" "${DEFAULT_PATH}"
    
    printf "${GREEN}✓ Symbolic link created:${NC}\n"
    printf "  %s -> %s\n" "${DEFAULT_PATH}" "${JVM_DIR}/${new_default}"
}

# Remove default symbolic link
unset_default_link() {
    rm -f "${DEFAULT_PATH}" 2>/dev/null
}

# Ensure profile.d configuration exists
ensure_profile_config() {
    if [ ! -f "${JAVA_CONFIG_FILE}" ]; then
        printf "%bCreating system PATH configuration...%b\n" "${YELLOW}" "${NC}"
        
        # Create profile.d directory if needed
        mkdir -p "${SYSTEM_PROFILE_DIR}"
        
        # Create configuration file
        cat > "${JAVA_CONFIG_FILE}" << 'EOF'
# Java Default Environment Configuration
# This file adds the default Java to PATH

if [ -d /usr/lib/jvm/default/bin ]; then
    export PATH="/usr/lib/jvm/default/bin:${PATH}"
    export JAVA_HOME="/usr/lib/jvm/default"
fi
EOF
        chmod 644 "${JAVA_CONFIG_FILE}"
        printf "%b✓ Configuration file created:%b\n" "${GREEN}" "${NC}"
        printf "  %s\n" "${JAVA_CONFIG_FILE}"
    fi
}

# Show help
show_help() {
    printf "%b%bJava Version Manager (OpenJDK)%b\n\n" "${BOLD}" "${BLUE}" "${NC}"
    printf "%bUSAGE:%b\n" "${YELLOW}" "${NC}"
    printf "    %s <COMMAND>\n\n" "$(basename "$0")"
    printf "%bCOMMANDS:%b\n" "${YELLOW}" "${NC}"
    printf "    %bstatus%b              List installed Java environments and show default\n" "${BOLD}" "${NC}"
    printf "    %bget%b                 Return the name of the default Java environment\n" "${BOLD}" "${NC}"
    printf "    %bset <VERSION>%b       Set Java version as default (requires root)\n" "${BOLD}" "${NC}"
    printf "    %bunset%b               Remove default Java configuration (requires root)\n" "${BOLD}" "${NC}"
    printf "    %bhelp%b, %b-h%b, %b--help%b   Show this help\n\n" "${BOLD}" "${NC}" "${BOLD}" "${NC}" "${BOLD}" "${NC}"
    printf "%bEXAMPLES:%b\n" "${YELLOW}" "${NC}"
    printf "    # List installed versions\n"
    printf "    %s status\n\n" "$(basename "$0")"
    printf "    # Get current default\n"
    printf "    %s get\n\n" "$(basename "$0")"
    printf "    # Set Java 17 as default\n"
    printf "    doas %s set 17\n\n" "$(basename "$0")"
    printf "    # Set Java 25 as default\n"
    printf "    doas %s set java-25-openjdk\n\n" "$(basename "$0")"
    printf "    # Remove default\n"
    printf "    doas %s unset\n\n" "$(basename "$0")"
    printf "%bHOW IT WORKS:%b\n" "${YELLOW}" "${NC}"
    printf "    This script uses symbolic links instead of modifying PATH:\n"
    printf "    1. Creates link: %s -> /usr/lib/jvm/java-XX-openjdk\n" "${DEFAULT_PATH}"
    printf "    2. System PATH includes: /usr/lib/jvm/default/bin\n"
    printf "    3. Changes apply immediately, no 'source' needed!\n\n"
    printf "%bINSTALLATION:%b\n" "${YELLOW}" "${NC}"
    printf "    # Install script system-wide\n"
    printf "    doas cp %s /usr/bin/venom-java-manager\n" "$(basename "$0")"
    printf "    doas chmod +x /usr/bin/venom-java-manager\n"
    printf "    \n"
    printf "    # Setup initial configuration\n"
    printf "    doas venom-java-manager set 17\n\n"
    printf "%bNOTES:%b\n" "${YELLOW}" "${NC}"
    printf "    - Versions are in: %s\n" "${JVM_DIR}"
    printf "    - Default link: %s\n" "${DEFAULT_PATH}"
    printf "    - PATH config: %s\n" "${JAVA_CONFIG_FILE}"
    printf "    - Only 'set' and 'unset' require root\n"
    printf "    - Changes are immediate\n\n"
}

# Show status
do_status() {
    installed_javas=$(get_installed_javas)
    
    if [ -z "$installed_javas" ]; then
        printf "${YELLOW}No compatible Java environments installed${NC}\n"
        return 0
    fi
    
    default_java=$(get_default_java)
    
    printf "${BLUE}Available Java environments:${NC}\n"
    for java in $installed_javas; do
        if [ "$java" = "$default_java" ]; then
            printf "  ${GREEN}%s (default)${NC}\n" "$java"
        else
            printf "  %s\n" "$java"
        fi
    done
    
    if [ -z "$default_java" ]; then
        printf "\n${YELLOW}No Java environment set as default${NC}\n"
    else
        printf "\n${GREEN}Current default:${NC} %s\n" "$default_java"
        
        # Show Java version
        if [ -x "${DEFAULT_PATH}/bin/java" ]; then
            printf "\n${BLUE}Version information:${NC}\n"
            "${DEFAULT_PATH}/bin/java" -version 2>&1 | head -n 3
        fi
    fi
}

# Get default
do_get() {
    default_java=$(get_default_java)
    if [ -n "$default_java" ]; then
        echo "$default_java"
    else
        printf "${YELLOW}No default Java environment set${NC}\n" >&2
        return 1
    fi
}

# Set default Java environment
# $1: Java environment name
do_set() {
    check_root "$@"
    
    version="$1"
    
    if [ -z "$version" ]; then
        printf "${RED}Error: You must specify a version${NC}\n"
        printf "Example: doas %s set 17\n" "$(basename "$0")"
        return 1
    fi
    
    # Normalize version name
    if ! echo "$version" | grep -q "^java-"; then
        version="java-${version}-openjdk"
    fi
    
    # Find exact match
    java_path=""
    for dir in "${JVM_DIR}"/$version*; do
        if [ -d "$dir" ] && [ -x "$dir/bin/java" ]; then
            java_path=$(basename "$dir")
            break
        fi
    done
    
    if [ -z "$java_path" ] || ! is_java_valid "$java_path"; then
        printf "${RED}Error: '%s' is not a valid Java environment${NC}\n" "$version"
        printf "\n${YELLOW}Available versions:${NC}\n"
        for java in $(get_installed_javas); do
            printf "  %s\n" "$java"
        done
        return 1
    fi
    
    # Check if already set
    current_default=$(get_default_java)
    if [ "$java_path" = "$current_default" ]; then
        printf "${YELLOW}Java %s is already set as default${NC}\n" "$java_path"
        return 0
    fi
    
    printf "${BLUE}Setting Java %s as system default...${NC}\n" "$java_path"
    
    # Ensure profile.d configuration exists
    ensure_profile_config
    
    # Unset old link and set new one
    unset_default_link
    set_default_link "$java_path"
    
    printf "\n${GREEN}✓ Java version set successfully${NC}\n"
    printf "${GREEN}✓ Changes are immediately effective${NC}\n\n"
    
    # Show how to verify
    printf "${YELLOW}Verify in current shell:${NC}\n"
    printf "    java -version\n"
    printf "    which java\n\n"
    
    printf "${YELLOW}If java is not found, reload your shell:${NC}\n"
    printf "    source %s\n" "${JAVA_CONFIG_FILE}"
    printf "    ${YELLOW}or open a new terminal${NC}\n"
}

# Unset default
do_unset() {
    check_root "$@"
    
    if [ ! -L "${DEFAULT_PATH}" ]; then
        printf "${YELLOW}No default Java environment set${NC}\n"
        return 0
    fi
    
    printf "${BLUE}Removing default Java configuration...${NC}\n"
    
    unset_default_link
    
    printf "${GREEN}✓ Default Java environment removed${NC}\n"
}

# Main function
main() {
    case "${1:-}" in
        status)
            do_status
            ;;
        get)
            do_get
            ;;
        set)
            shift
            do_set "$@"
            ;;
        unset)
            shift
            do_unset "$@"
            ;;
        help|-h|--help|'')
            show_help
            ;;
        *)
            printf "${RED}Error: Unknown command: '%s'${NC}\n\n" "$1"
            show_help
            exit 1
            ;;
    esac
}

# Execute main function
main "$@"
