#!/bin/bash -eu
# SPDX-FileCopyrightText: 2025 Uwe Fechner
# SPDX-License-Identifier: MIT

_yes_to_all=false

print_usage() {
    echo "Usage:"
    echo "./install"
    echo "./install -y"
    echo "./install --yes"
    echo "./install -h"
    echo "./install --help"
    echo "Options:"
    echo "  -y, --yes     Automatically choose the default Julia version without prompting."
    echo "  -h, --help    Show this help message and exit."
}

# Parse command line arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            print_usage
            exit 0
            ;;
        -y|--yes)
            _yes_to_all=true
            shift
            ;;
        *)
            echo "Invalid parameter!"
            print_usage
            exit 1
            ;;
    esac
done

if [[ $(basename $(pwd)) == "bin" ]]; then
    cd ..
fi

# Check if juliaup is installed
if ! command -v juliaup &> /dev/null; then
    echo "Error: juliaup is not installed. Please install it first."
    case "$(uname -s)" in
        Linux|Darwin)
            echo "  curl -fsSL https://install.julialang.org | sh -s -- --default-channel 1.11"
            ;;
        MINGW*|MSYS*|CYGWIN*)
            echo "  winget install --name Julia --id 9NJNWW8PVKMN -e -s msstore"
            ;;
        *)
            echo "  See https://github.com/JuliaLang/juliaup for installation instructions."
            ;;
    esac
    exit 1
fi

# Ask which Julia version to use.
# Default to 1.12 if it is already the current default, otherwise 1.11.
if juliaup status 2>/dev/null | grep '^\s*\*' | grep -q '1\.12'; then
    _default_choice=2
    _default_julia="1.12"
else
    _default_choice=1
    _default_julia="1.11"
fi

echo "Which Julia version do you want to use?"
echo "  1) Julia 1.11"
echo "  2) Julia 1.12"
if [[ $_yes_to_all == true ]]; then
    _julia_choice=""
    echo "Using Julia version: ${_default_julia}"
else
    read -rp "Enter 1 or 2 [default: ${_default_choice}]: " _julia_choice
fi

case "${_julia_choice}" in
    1)
        _desired_julia="1.11"
        ;;
    2)
        _desired_julia="1.12"
        ;;
    "")
        _desired_julia="${_default_julia}"
        ;;
    *)
        echo "Invalid choice: '${_julia_choice}'. Please enter 1 or 2."
        exit 1
        ;;
esac

echo "Installing and activating Julia ${_desired_julia}..."
juliaup add "${_desired_julia}"
juliaup default "${_desired_julia}"
echo "Julia ${_desired_julia} is now the default."
echo

# Detect Julia version
julia_version=$(julia --version | awk '{print($3)}')
julia_major=${julia_version:0:3}
if [[ $julia_major == "1.1" ]]; then
    julia_major=${julia_version:0:4} 
fi

echo "Detected Julia version: $julia_version (major: $julia_major)"

export JULIA_PKG_SERVER_REGISTRY_PREFERENCE=eager

# Delete any existing custom system image for this Julia version
SOFILE="bin/kps-image-${julia_major}.so"
if test -f "$SOFILE"; then
    echo "Deleting old system image: $SOFILE"
    rm -f "$SOFILE"
fi
if compgen -G "bin/kps-image-${julia_major}-*.so" > /dev/null; then
    echo "Deleting legacy branch-specific system images for Julia ${julia_major}"
    rm -f bin/kps-image-"${julia_major}"-*.so
fi

# Only accept Julia 1.11 and 1.12
if [[ $julia_major != "1.11" ]] && [[ $julia_major != "1.12" ]]; then
    echo "Error: Julia $julia_major is not supported. Only Julia 1.11 and 1.12 are supported."
    echo "You can install Julia 1.11 with the following commands:"
    echo "juliaup add 1.11"
    echo "juliaup default 1.11"
    exit 1
fi

# Copy LocalPreferences if not present
if [ ! -f "LocalPreferences.toml" ]; then
    if [ -f "LocalPreferences.toml.default" ]; then
        cp LocalPreferences.toml.default LocalPreferences.toml
        echo "Copied LocalPreferences.toml.default to LocalPreferences.toml"
    fi
fi

# Copy the appropriate default manifest
if [[ $julia_major == "1.11" ]]; then
    if [ -f "Manifest-v1.11.toml.default" ]; then
        cp Manifest-v1.11.toml.default Manifest-v1.11.toml
        echo "Copied Manifest-v1.11.toml.default to Manifest-v1.11.toml"
    else
        echo "Warning: Manifest-v1.11.toml.default not found"
        exit 1
    fi
else
    # Default to 1.12 for newer versions
    if [ -f "Manifest-v1.12.toml.default" ]; then
        cp Manifest-v1.12.toml.default Manifest-v1.12.toml
        echo "Copied Manifest-v1.12.toml.default to Manifest-v1.12.toml"
    else
        echo "Warning: Manifest-v1.12.toml.default not found"
        exit 1
    fi
fi

# Instantiate the project
echo "Instantiating project..."
julia --project -e '
using Pkg
try
    Pkg.instantiate()
catch e
    @warn "Pkg.instantiate() failed, attempting fresh resolve..." exception=e
    proj_dir = dirname(Base.active_project())
    # Remove all manifest files to force a clean resolve
    for f in readdir(proj_dir)
        if startswith(f, "Manifest") && endswith(f, ".toml") && !endswith(f, ".default")
            rm(joinpath(proj_dir, f), force=true)
        end
    end
    Pkg.resolve()
    Pkg.instantiate()
end
'
echo "Precompiling main project..."
julia --project -e 'using Pkg; Pkg.precompile()'

# Julia may write a generic Manifest.toml instead of Manifest-v${julia_major}.toml.
# Rename it so the install script can seed sub-projects from the correct versioned file.
if [ -f "Manifest.toml" ] && [ ! -f "Manifest-v${julia_major}.toml" ]; then
    mv Manifest.toml "Manifest-v${julia_major}.toml"
    echo "Renamed Manifest.toml to Manifest-v${julia_major}.toml"
fi

# Instantiate all sub-projects: examples, test, docs
echo "Julia $julia_major: instantiating all sub-projects..."
# Seed subproject manifests from the main manifest only for Julia 1.11.
# For Julia 1.12, keep no manifests in subprojects.
rm -f examples/Manifest*.toml test/Manifest*.toml
if [[ $julia_major == "1.11" ]]; then
    cp "Manifest-v${julia_major}.toml" "examples/Manifest-v${julia_major}.toml"
    cp "Manifest-v${julia_major}.toml" "test/Manifest-v${julia_major}.toml"
fi

# Develop the main package into the sub-project environments so Julia finds the local source.
julia --project=examples -e 'using Pkg; Pkg.develop(PackageSpec(path=".")); Pkg.resolve(); Pkg.instantiate()'
echo "Precompiling examples project..."
julia --project=examples -e 'using Pkg; Pkg.precompile()'

julia --project=test -e 'using Pkg; Pkg.develop(PackageSpec(path=".")); Pkg.resolve(); Pkg.instantiate()'
echo "Precompiling test project..."
julia --project=test -e 'using Pkg; Pkg.precompile()'

# Docs resolves independently (different dep tree; seeding from main causes missing extensions)
rm -f docs/Manifest*.toml
julia --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=".")); Pkg.resolve(); Pkg.instantiate()'
echo "Precompiling docs project..."
julia --project=docs -e 'using Pkg; Pkg.precompile()'

# Rename manifest files to version-specific names
if [[ $julia_major == "1.11" ]] && [ -f "examples/Manifest.toml" ]; then
    mv examples/Manifest.toml examples/Manifest-v${julia_major}.toml
    echo "Renamed examples/Manifest.toml to examples/Manifest-v${julia_major}.toml"
fi
if [ -f "test/Manifest.toml" ]; then
    if [[ $julia_major == "1.11" ]]; then
        mv test/Manifest.toml test/Manifest-v${julia_major}.toml
        echo "Renamed test/Manifest.toml to test/Manifest-v${julia_major}.toml"
    fi
fi
if [ -f "docs/Manifest.toml" ]; then
    if [[ $julia_major == "1.11" ]]; then
        mv docs/Manifest.toml docs/Manifest-v${julia_major}.toml
        echo "Renamed docs/Manifest.toml to docs/Manifest-v${julia_major}.toml"
    fi
fi

if [[ $julia_major == "1.12" ]]; then
    rm -f examples/Manifest*.toml test/Manifest*.toml docs/Manifest*.toml
    echo "Removed subproject manifests for Julia 1.12"
fi

# Add alias to shell configuration file
if [[ "$(uname -s)" == "Linux" && -f ~/.bashrc ]]; then
    if ! grep -q "alias jl='bin/run_julia'" ~/.bashrc; then
        echo "alias jl='bin/run_julia'" >> ~/.bashrc
        echo
        echo "Added alias 'jl' to ~/.bashrc"
        echo "Run 'source ~/.bashrc' or restart your terminal to use it"
    fi
elif [[ "$(uname -s)" == "Darwin" ]]; then
    # On macOS, check for zsh (default since Catalina) or bash configuration files
    _config_file=""
    if [[ -f ~/.zshrc ]]; then
        _config_file=~/.zshrc
    elif [[ -f ~/.bash_profile ]]; then
        _config_file=~/.bash_profile
    elif [[ -f ~/.bashrc ]]; then
        _config_file=~/.bashrc
    fi
    
    if [[ -n "$_config_file" ]]; then
        if ! grep -q "alias jl='bin/run_julia'" "$_config_file"; then
            echo "alias jl='bin/run_julia'" >> "$_config_file"
            echo
            echo "Added alias 'jl' to $_config_file"
            echo "Run 'source $_config_file' or restart your terminal to use it"
        fi
    fi
    unset _config_file
fi

echo "Installation complete!"
echo
echo "You can now launch Julia by typing"
echo "cd .."
echo "./bin/run_julia"
