#!/bin/bash
VERSION=@VERSION@
# 获取脚本名称用于帮助信息
SCRIPT_NAME=$(basename "$0")
PATH_PREFIX=/var/lib/apm/apm/files/ace-env/

log.warn() { echo -e "[\e[33mWARN\e[0m]:  \e[1m$*\e[0m"; }
log.error()  { echo -e "[\e[31mERROR\e[0m]: \e[1m$*\e[0m"; }
log.info() { echo -e "[\e[96mINFO\e[0m]:  \e[1m$*\e[0m"; }
log.debug()  { echo -e "[\e[32mDEBUG\e[0m]: \e[1m$*\e[0m"; }

# 帮助信息函数
show_help() {
    cat <<EOF
APM - Amber Package Manager ${VERSION}

Usage:
  $SCRIPT_NAME [COMMAND] [OPTIONS] [PACKAGES...]


Commands:
  install           安装软件包
  remove            卸载软件包
  launch <package> [args...]  启动软件包（通过应用启动器）
  run <package> [EXEC_PATH] [args...]  运行指定软件包的可执行文件（可指定容器内路径）
  sandbox-run <package> [EXEC_PATH] [args...] 运行指定软件包的可执行文件（主目录沙箱化）
  bwrap-run <package> [EXEC_PATH] [args...] 运行指定软件包的可执行文件（使用特殊的挂载参数以支持bwrap）

  update            更新软件包信息
  hold              锁定软件包版本
  unhold            解锁软件包版本
  full-upgrade      升级全部软件包
  list              查看可用软件包信息
  search            搜索软件包

  download          下载包
  show              展示包信息
  clean             清除缓存软件包
  autoremove        自动移除不需要的包
  ssaudit <path>    使用 ssaudit 进行本地软件安装，详情见 spark-store
  debug             显示调试系统信息并进入调试环境

  amber             彩蛋功能
  xmp360            彩蛋功能
  bronya            彩蛋功能

  -h, --help        显示此帮助信息
  -v, --version     展示APM版本号

                                            本 APM 具有兔兔伯爵，女武神装甲和超级大运之力。
EOF
}

apm_exec(){
    # ===============================
    # 基础变量
    # ===============================
    local lowerdirs=()
    local env_layers=()
    local current_dir="${PATH_PREFIX}/var/lib/apm/${coredir}"
    local next_info_file=""
    local APM_RUN_EXEC=/var/lib/apm/apm/files/ace-run

    # ===============================
    # 递归读取 info / info_env
    # ===============================
    while : ; do
        next_info_file="${current_dir}/info"

        # 记录 info_env（底层优先）
        if [[ -f "${current_dir}/info_env" ]]; then
            env_layers+=("${current_dir}/info_env")
        fi

        # 没有 info 就停止
        [[ ! -f "$next_info_file" ]] && break

        # 读取依赖层
        while IFS= read -r basedir; do
            [[ -z "$basedir" ]] && continue

            if [[ -d "${PATH_PREFIX}/var/lib/apm/${basedir}/files/ace-env" ]]; then
                lowerdirs+=("${PATH_PREFIX}/var/lib/apm/${basedir}/files/ace-env")
            elif [[ -d "${PATH_PREFIX}/var/lib/apm/${basedir}/files/core" ]]; then
                lowerdirs+=("${PATH_PREFIX}/var/lib/apm/${basedir}/files/core")
            else
                log.warn "Neither ace-env nor core directory found for base: $basedir"
            fi
        done < "$next_info_file"

        # 递归到下一个
        local next_basedir
        next_basedir="$(tail -n 1 "$next_info_file")"
        [[ -z "$next_basedir" || ! -d "${PATH_PREFIX}/var/lib/apm/${next_basedir}" ]] && break
        current_dir="${PATH_PREFIX}/var/lib/apm/${next_basedir}"
    done

    # ===============================
    # info_layer_override（最高优先级）
    # ===============================
    local override_file="${PATH_PREFIX}/var/lib/apm/${coredir}/info_layer_override"
    if [[ -f "$override_file" ]]; then
        log.debug "Found info_layer_override: $override_file"

        local override_dirs=()
        local override_envs=()

        while IFS= read -r basedir; do
            [[ -z "$basedir" ]] && continue
            local base="${PATH_PREFIX}/var/lib/apm/${basedir}"

            if [[ -d "${base}/files/ace-env" ]]; then
                override_dirs+=("${base}/files/ace-env")
            elif [[ -d "${base}/files/core" ]]; then
                override_dirs+=("${base}/files/core")
            else
                log.warn "Override layer not found: $basedir"
            fi

            if [[ -f "${base}/info_env" ]]; then
                override_envs+=("${base}/info_env")
            fi
        done < "$override_file"

        # override 层放最前（最高）
        if [[ ${#override_dirs[@]} -gt 0 ]]; then
            lowerdirs=("${override_dirs[@]}" "${lowerdirs[@]}")
        fi

        # override env 最后应用（最高）
        if [[ ${#override_envs[@]} -gt 0 ]]; then
            env_layers+=("${override_envs[@]}")
        fi
    fi

    # ===============================
    # 检查 lowerdir
    # ===============================
    if [[ ${#lowerdirs[@]} -eq 0 ]]; then
        log.error "No valid lower directories found for package: $coredir"
        return 1
    fi

    local lowerdir
    lowerdir=$(IFS=:; echo "${lowerdirs[*]}")

    mkdir -p "/tmp/apm/${coredir}"

    # ===============================
    # 应用 info_env（从下到上）
    # ===============================
    for env_file in "${env_layers[@]}"; do
        log.debug "Applying env: $env_file"

        while IFS= read -r line || [[ -n "$line" ]]; do
            [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue

            if [[ "$line" =~ ^[A-Za-z_][A-Za-z0-9_]*= ]]; then
                local key="${line%%=*}"
                local val="${line#*=}"

                # 去首尾空白
                val="${val#"${val%%[![:space:]]*}"}"
                val="${val%"${val##*[![:space:]]}"}"

                # 去外层引号
                if [[ "$val" =~ ^\".*\"$ || "$val" =~ ^\'.*\'$ ]]; then
                    val="${val:1:-1}"
                fi

                export "$key=$val"
            else
                log.warn "Invalid env line ignored: $line"
            fi
        done < "$env_file"
    done

    # ===============================
    # 挂载 overlay
    # ===============================
    log.debug "Mounting overlayfs"
    log.debug "lowerdir=$lowerdir"

    fuse-overlayfs \
        -o lowerdir="$lowerdir",upperdir="${PATH_PREFIX}/var/lib/apm/${coredir}/files/core/",workdir="${PATH_PREFIX}/var/lib/apm/${coredir}/files/work/" \
        "/tmp/apm/${coredir}"

    # ===============================
    # 执行
    # ===============================
    chrootEnvPath="/tmp/apm/${coredir}" "${APM_RUN_EXEC}" "$@"

    # ===============================
    # 卸载
    # ===============================
    umount "/tmp/apm/${coredir}"
}

# 启动应用：通过 amber-pm-app-launcher 运行
apm_launch() {
    local pkg="$1"
    shift
    if [ -z "$pkg" ]; then
        log.error "Package name required for 'launch' command"
        return 1
    fi

    # 保存原始 PATH_PREFIX，检查包是否存在（逻辑同 run 分支）
    local original_path_prefix="$PATH_PREFIX"
    if ! [ -d "${PATH_PREFIX}/var/lib/apm/$pkg" ]; then
        if [ -d "/var/lib/apm/$pkg" ]; then
            PATH_PREFIX=""
        else
            log.error "Package not installed: $pkg"
            return 1
        fi
    fi

    # 调用应用启动器，传递所有参数
    amber-pm-app-launcher "$pkg" "$@"
    local exit_code=$?

    # 恢复 PATH_PREFIX（不影响后续命令）
    PATH_PREFIX="$original_path_prefix"
    return $exit_code
}

# 调试信息函数
debug_info() {
    log.debug "======= APM Debug Information ======="
    log.debug "User: $(whoami)"
    log.debug "Hostname: $(hostname)"
    log.debug "OS: $(lsb_release -ds 2>/dev/null || uname -om)"
    log.debug "Kernel: $(uname -sr)"
    log.debug "Bash Version: ${BASH_VERSION}"
    log.debug "APT Version: $(apt --version | head -n1)"
    log.debug "APM APT Version: $(amber-pm-debug apt --version | head -n1)"
    log.debug "====================================="

amber-pm-debug "$@"

}

# 彩蛋函数
amber_egg() {
    cat <<'EOF'

    ____                            ____                         
   / __ )____ __________  ____     / __ )__  ______  ____  __  __
  / __  / __ `/ ___/ __ \/ __ \   / __  / / / / __ \/ __ \/ / / /
 / /_/ / /_/ / /  / /_/ / / / /  / /_/ / /_/ / / / / / / / /_/ / 
/_____/\__,_/_/   \____/_/ /_/  /_____/\__,_/_/ /_/_/ /_/\__, /  
                                                        /____/   

Amber Package Manager - Sparkling with magic! 安柏包管理器 - blingbling～
💎 Another target tracked down by Outrider Amber! 侦察骑士，发现目标！
EOF
}

bronya_egg() {
    cat <<'EOF'
  _   __     ____            _       ____         __              
 | | / /__ _/ / /____ ______(_)__   / __/_ _____ / /____ __ _     
 | |/ / _ `/ /  '_/ // / __/ / _-) _\ \/ // (_-</ __/ -_)  ' \    
 |___/\_,_/_/_/\_\\_, /_/ /_/\__/ /___/\_, /___/\__/\__/_/_/_/    
  / /  ___ ___ __/___/____/ /         /___/                       
 / /__/ _ `/ // / _ \/ __/ _ \                                    
/____/\_,_/_,_/_//_/\__/_//_/        

Valkyrie 系统启动 - 重装小兔，Fire！
💎 感谢 Anysets 为 AmberCE 和 AmberPM 的 Arch 架构支持提供帮助～
EOF
}

xmp360_egg() {
    cat <<'EOF'
################################################################################
################################################################################
################################################################################
#####################                                       ####################
####################.                                       %###################
##########=                                                 ####################
############################                                #=========*#########
#############                                              .%   .*****=  :######
###############################                            =+   =#######* -#####
#####                                                      %:   *######## :#####
######################%                                    #    ########* +#####
########:                                                  #              %#####
##########################                                .#              ######
##################*                                       -*              ######
##################=        =###%:                         +-    *###*     ######
##################.      #       %:                          :*       #  -######
##################.     %  *###=  %                         --  ####   % %######
########################-  ####+  ###########################  .####.  #########
#########################        ############################%        ##########
###########################=::+################################%-:-*############
################################################################################

哇——————袄 - 撞大运咯！
💎 感谢 潇湘·秀 为 APM 的 RPM 架构支持提供帮助～
EOF
}

apm-nvidia-toggle(){

# APM 基础路径
APM_BASE="${PATH_PREFIX}/var/lib/apm"

# 检查基础目录是否存在
if [[ ! -d "$APM_BASE" ]]; then
    echo "错误: 目录 $APM_BASE 不存在"
    exit 1
fi

# 遍历 /var/lib/apm 下的所有目录
for dir in "$APM_BASE"/*/; do
    # 移除末尾的斜杠得到纯目录名
    dir="${dir%/}"
    
    # 提取目录名（不包括完整路径）
    dirname=$(basename "$dir")
    # 检查目标文件是否存在
    target_file="${APM_BASE}/${dirname}/files/ace-env"
    if [[ -e "$target_file" ]]; then
        
        # 将目录传递给 amber-pm-configure-nvidia
        amber-pm-configure-nvidia "$target_file"
        

    fi
done
}
# 主命令处理
case "$1" in
    install|full-upgrade|upgrade|reinstall)
    command=$1
    shift
    amber-pm-debug aptss "$command" "$@"
        exit_code=$?
    if [ $exit_code -eq 0 ]; then
        log.info "Operation successful"
    else
        log.error "Error: Operation failed"
        exit $exit_code
    fi
    amber-pm-debug amber-pm-dstore-patch
    apm-nvidia-toggle
    amber-pm-gxde-desktop-fix
    ;;
    download|search|policy|list|update|clean|show|depends|rdepends|changelog|moo)
    command=$1
    shift
    amber-pm-debug aptss "$command" "$@"
        exit_code=$?
    if [ $exit_code -eq 0 ]; then
        log.info "Operation successful"
    else
        log.error "Error: Operation failed"
        exit $exit_code
    fi
    ;;
    hold|unhold)
    command=$1
    shift
    amber-pm-debug apt-mark "$command" "$@"
        exit_code=$?
    if [ $exit_code -eq 0 ]; then
        log.info "Operation successful"
    else
        log.error "Error: Operation failed"
        exit $exit_code
    fi
    ;;

   remove|autoremove|purge|autopurge)
        # 特殊APT命令：移除第一个参数后传递其余参数
        command=$1
        shift
        amber-pm-debug aptss "$command" "$@"
        exit_code=$?
    if [ $exit_code -eq 0 ]; then
        log.info "Operation successful"
    else
        log.error "Error: Operation failed"
        exit $exit_code
    fi
        amber-pm-debug amber-pm-dstore-patch
        amber-pm-gxde-desktop-fix
        ;;
   launch)
        shift
        apm_launch "$@"
        exit_code=$?
        if [ $exit_code -eq 0 ]; then
            log.info "Operation successful"
        else
            log.error "Error: Operation failed"
            exit $exit_code
        fi
        ;;
   run)
        # 运行包命令：第二个参数必须是包名
        if [ -z "$2" ]; then
            log.error "Package name required for 'run' command"
            show_help
            exit 1
        fi
        
        # 检查包是否已安装
        pkg="$2"
        shift 2  # 移除 'run' 和包名
        
        if ! ls "${PATH_PREFIX}/var/lib/apm/$pkg" >/dev/null 2>&1; then
        # 如果带前缀的目录不存在，尝试不带前缀的目录
            if ls "/var/lib/apm/$pkg" >/dev/null 2>&1; then
                # 如果不带前缀的目录存在，清空 PATH_PREFIX
                PATH_PREFIX=""
            else
                # 如果两个目录都不存在，报错退出
                log.error "Package not installed: $pkg"
                exit 1
            fi
        fi
        
        coredir=$pkg
        export APM_PKG_NAME=$pkg

        # 检测是否有额外命令参数
        if [ $# -gt 0 ]; then
            # 有额外参数：执行用户提供的命令
            log.info "Running user command: $*"
            apm_exec "$@"
        else
            # 没有额外参数：提示用户改用 launch，并自动调用 launch
            log.info "未指定可执行文件路径。如果希望在未指定容器路径的情况下启动应用程序，推荐使用 "launch" 命令"
            log.info "正在启动：$SCRIPT_NAME launch $pkg"
            apm_launch "$pkg"
            exit $?
        fi
        ;;
   sandbox-run)
        # 运行包命令：第二个参数必须是包名
        export APM_USE_SANDBOX=1
        shift
        $0 run "$@"
        ;;
   bwrap-run)
        # 运行包命令：使用特殊的挂载参数以支持bwrap
        export APM_USE_BWRAP=1
        shift
        $0 run "$@"
        ;;
    debug)
        shift
        debug_info $@
        ;;
    ssaudit)
        amber-pm-debug ssaudit $@ --native
        exit_code=$?
    if [ $exit_code -eq 0 ]; then
        log.info "Operation successful"
    else
        log.error "Error: Operation failed"
        exit $exit_code
    fi
        amber-pm-debug amber-pm-dstore-patch
        amber-pm-gxde-desktop-fix

        ;;
    -h|--help)
        show_help
        ;;
    -v|--version)
        echo "$VERSION"
        ;;
    amber)
        amber_egg
        ;;
    xmp360)
        xmp360_egg
        ;;
    bronya)
        bronya_egg
        ;;
    *)
        show_help
        ;;
esac