#!/bin/bash
#
#  Copyright (c) 2024-2025 National Fundamental Software of China Co., Ltd.
#
#  You should have find a copy of NFSChina License. If not, please contact us
#  by email <os_support@nfschina.com>
#

PROGRAM="$0"
PARAMS=("$@")

if [ -L /opt ]; then
    OPT_REAL_PATH=$(readlink -f /opt)
fi

if [ "$HOTPOT_MANAGER_DEBUG" == "1" ]; then
    set -x
fi

# 解析参数
if (($# < 2)); then
    echo "参数错误"
    exit
fi

source /opt/winux/tools/appmanager/common.sh

# sayzhimakaimen 打印最终执行的命令行
param_count=$#
SAYZHIMAKAIMEN=""
if [ "${!param_count}" == "sayzhimakaimen" ]; then
    SAYZHIMAKAIMEN="1"
    # 赋值后，删除 sayzhimakaimen 参数
    set -- "${@:1:param_count-1}"
    echo -e "\033[0;32m#!/bin/bash\033[0m"
fi

APP_NAME="$1"
APP_VERSION="$2"
ACTION="$3"

# 计算 WINEPREFIX
param_count=$#
param_apppath=$(expr $param_count - 1)
if [ "${!param_apppath}" == "--apppath" ]; then
    WINEPREFIX="${!param_count}"
    # 赋值后，删除 --apppath /path/to/prefix 两个参数
    set -- "${@:1:param_count-2}"
else
    WINEPREFIX="/opt/winux/hotpot/appstore/${APP_NAME}-${APP_VERSION}"
fi
WINEPREFIX="$(realpath "$WINEPREFIX")"
if [ -L /opt ]; then
    WINEPREFIX=/opt"${WINEPREFIX#$OPT_REAL_PATH}"
fi
export WINEPREFIX
if [ "$WINEPREFIX" == "" ] || [ "${WINEPREFIX:0:1}" != "/" ] || [ "$(dirname "$WINEPREFIX")" == "/" ] || [ "$(dirname "$WINEPREFIX")" == "/home" ] || [ "$WINEPREFIX" == "$APPS_ROOT_PATH" ] || [ "$WINEPREFIX" == "/opt/winux/hotpot/appstore" ]; then
    echo "失败：不允许使用的目录"
    exit 1
fi

JSON_FILE="$(get_json_file_nocreate)"

# 赋值后，删除 APP_NAME，APP_VERSION 和 ACTION 三个参数，剩余参数为 wine 要执行的命令
shift 3

if [ "$ZHIMAKAIMEN" != "" ]; then
    shift ${ZHIMAKAIMEN}
    # eval echo "\$${ZHIMAKAIMEN}"
    echo "$1"
    exit
fi

TIME_STAMP="$(date +%N)"

function install_app() {
    # 复制桌面快捷方式
    remove_path "${JSON_FILE}" &>/dev/null
    export DPKG_MAINTSCRIPT_PACKAGE_VERSION="$(dpkg-query -W -f='${Version}' "${DPKG_MAINTSCRIPT_PACKAGE:-$1}")"
    remove_path "${WINEPREFIX}/.cache"
    touch "${WINEPREFIX}/.cache"
    refreshappdetail
    local packagename="$(cat "$JSON_FILE" | jq -r .packagename)"
    if jq_none "$packagename"; then
        return 1
    fi

    # Apply conditional registry fixes (GPU/arch-specific .reg imports)
    /opt/winux/tools/appmanager/apply-conditional-regs.sh "$WINEPREFIX"

    /opt/winux/tools/appmanager/yuanyanghotpot-sudoer.sh username "install-desktop" --apppath "$WINEPREFIX"

    # 复制文件关联desktop文件
    /opt/winux/tools/appmanager/yuanyanghotpot-sudoer.sh usrname "install-fileassociations" --apppath "$WINEPREFIX"

    if [ -f "${WINEPREFIX}/${packagename}.patch.sh" ]; then
        source "${WINEPREFIX}/${packagename}.patch.sh"
        deb_postinst
    elif [ -f "/opt/winux/hotpot-manager/patch/${packagename}.patch.sh" ]; then
        source "/opt/winux/hotpot-manager/patch/${packagename}.patch.sh"
        deb_postinst
    fi

    chmod -R 777 "$WINEPREFIX"
    # chown -R 1000:1000 "${WINEPREFIX}"
    local all_users="$(list_normal_users)"
    for user_name in ${all_users[@]}; do
        # 清理wine生成的desktop
        if [ -d "/home/${user_name}/.local/share/applications" ]; then
            while read line; do
                if [ -f "${line}" ]; then
                    remove_path "${line}"
                fi
            done < <(grep -rwl "$packagename" "/home/${user_name}/.local/share/applications/")
        fi
        # 拷贝driver_c/users/ 中所有用户目录
        su $user_name -c "source /opt/winux/tools/appmanager/common.sh ; make_special_user_dir \"$user_name\"" &
        local job_pid=$!
        (
            sleep 5
            kill -9 $job_pid &>/dev/null
        ) &
        local timeout_pid=$!
        wait $job_pid
        kill -9 $timeout_pid &>/dev/null
    done

    # 通知火锅平台客户端
    SendToHotpotUI "Refreshpage"

    return 0
}

function uninstall_app() {
    # 幂等保护：容器可能已被yuanyanghotpot prerm清理
    if [ ! -d "$WINEPREFIX" ] || [ ! -f "$JSON_FILE" ]; then
        return 0
    fi

    local all_users="$(list_normal_users)"
    # 如果应用正在运行，先关闭
    while read line; do
        local prefix="$(echo "${line}" | awk '{print $1}')"
        prefix="$(realpath -s "${prefix}")"
        if [ "${WINEPREFIX}" == "${prefix}" ]; then
            local wineserver_cmd="$(echo "${line}" | awk '{print $2}')"
            for user_name in ${all_users[@]}; do
                su $user_name -c "WINEPREFIX="$WINEPREFIX" "$wineserver_cmd" -kw &>/dev/null" &
                local job_pid=$!
                (
                    sleep 3
                    kill -9 $job_pid &>/dev/null
                ) &
                local timeout_pid=$!
                wait $job_pid
                kill -9 $timeout_pid &>/dev/null
            done
            wineprc -k "$WINEPREFIX &>/dev/null"
            break
        fi
    done < <(/opt/winux/tools/appmanager/yuanyanghotpot-sudoer.sh usrname list-run-apps -a)

    local packagename="$(cat "$JSON_FILE" | jq -r .packagename)"
    if jq_none "$packagename"; then
        return 1
    fi

    # 删除desktop和icon
    /opt/winux/tools/appmanager/yuanyanghotpot-sudoer.sh username "remove-desktop" --apppath "$WINEPREFIX"

    # 删除文件关联
    for user_name in ${all_users[@]}; do
        if [ -d "/home/${user_name}/.local/share/applications" ]; then
            while read line; do
                if [ -f "${line}" ]; then
                    remove_path "${line}"
                fi
            done < <(grep -rwl "$packagename" "/home/${user_name}/.local/share/applications/")
        fi
    done
    /opt/winux/tools/appmanager/yuanyanghotpot-sudoer.sh username "remove-fileassociations" --apppath "$WINEPREFIX"

    if [ -f "/opt/winux/hotpot-manager/patch/${packagename}.patch.sh" ]; then
        source "/opt/winux/hotpot-manager/patch/${packagename}.patch.sh"
        deb_prerm
    fi
    if [ -f "${WINEPREFIX}/${packagename}.patch.sh" ]; then
        source "${WINEPREFIX}/${packagename}.patch.sh"
        deb_prerm
    fi

    # 删除容器
    # remove_path "$WINEPREFIX" &>/dev/null
    #原子重命名
    trash_root="/opt/winux/.trash"
    if [ ! -d "$trash_root" ]; then
        mkdir -p "$trash_root"
    fi
    gc_dir="$trash_root/$(basename "$WINEPREFIX").$$.$(date +%s%N)"
    mv "$WINEPREFIX" "$gc_dir"

    #后台慢慢删，不影响主流程
    (
        ionice -c3 nice -n 19 rm -rf "$gc_dir"
    ) &

    remove_path "${JSON_FILE}" &>/dev/null

    # 通知火锅平台客户端
    SendToHotpotUI "Refreshpage"

    return 0
}

function dimensions_to_dpi() {
    local autodpi="$(cat "$JSON_FILE" | jq -r .autodpi)"
    if ! jq_none "$autodpi"; then # 出错
        if (($1 < 1100)); then    # 1k 屏 - 默认96
            echo -n "$(echo $autodpi | jq -r .[0])"
        elif (($1 < 1500)); then # 2k 屏 - 默认120
            echo -n "$(echo $autodpi | jq -r .[1])"
        elif (($1 < 2200)); then # 4k 屏 - 默认240
            echo -n "$(echo $autodpi | jq -r .[2])"
        elif (($1 < 4400)); then # 8k 屏 - 默认288
            echo -n "$(echo $autodpi | jq -r .[3])"
        else # 出错
            echo -n 96
        fi
        return
    fi

    if (($1 < 1100)); then # 1k 屏
        echo -n 96
    elif (($1 < 1500)); then # 2k 屏
        echo -n 120
    elif (($1 < 2200)); then # 4k 屏
        echo -n 240
    elif (($1 < 4400)); then # 8k 屏
        echo -n 288
    else # 出错
        echo -n 96
    fi
}

make_app_dll_path_hotpot9() {
    if [ "$dlls_path_result" != "" ]; then
        local appDllPath="${WINEPREFIX}/override-dlls"
        local flag="0"
        IFS=':'
        for dlls_path in ${dlls_path_result[@]}; do
            # 判断是否有查分包？
            array_so=($(find "${dlls_path}/" -name "*.patch" | xargs))
            if [ "$array_so" == "" ]; then
                continue
            fi

            flag="1"

            # 判断是否已经解压过？
            if [ -d "$appDllPath" ]; then
                if [ -f $dlls_path/32 ]; then
                    if diff "${dlls_path}/32" "${appDllPath}/32" &>/dev/null; then
                        continue
                    fi
                elif [ -f $dlls_path/64 ]; then
                    if diff "${dlls_path}/64" "${appDllPath}/64" &>/dev/null; then
                        continue
                    fi
                fi
                remove_path "$appDllPath"
            fi
            mkdir "$appDllPath"
            cp -a "$dlls_path"/* "$appDllPath"/

            OLDIFS=$IFS
            IFS=' '
            array_so=($(find "$appDllPath/" -name "*.patch" | xargs))
            for so in ${array_so[@]}; do
                so=${so%.*}
                so_name=${so##*/}
                so_path=${so%/*}
                if echo "$so_path" | grep -q "i386-unix"; then
                    old_so=$WINE_PATH/lib/wine/i386-unix/$so_name
                elif echo "$so_path" | grep -q "i386-windows"; then
                    old_so=$WINE_PATH/lib/wine/i386-windows/$so_name
                elif echo "$so_path" | grep -q "x86_64-unix"; then
                    old_so=$WINE_PATH/lib/wine/x86_64-unix/$so_name
                elif echo "$so_path" | grep -q "x86_64-windows"; then
                    old_so=$WINE_PATH/lib/wine/x86_64-windows/$so_name
                else
                    break
                fi
                bspatch "$old_so" "$so" "$so.patch"
                remove_path "$so.patch"
            done
            IFS=$OLDIFS
        done
        IFS=' '
        if [ "$flag" == "1" ]; then
            dlls_path_result+=":"
            dlls_path_result+="${appDllPath}"
            run_or_print export HOTPOT_APPDLLPATH="${dlls_path_result}"
            chmod -R 777 "${appDllPath}"
        elif [ "$HOTPOT_APPDLLPATH" == "" ]; then
            run_or_print export HOTPOT_APPDLLPATH="${dlls_path_result}"
            remove_path "${appDllPath}" &>/dev/null
        else
            remove_path "${appDllPath}" &>/dev/null
        fi
    fi
}

make_app_dll_path() {
    dlls_path_result=""
    if [ -d "$HOTPOT_APPDLLPATH" ]; then
        dlls_path_result="$HOTPOT_APPDLLPATH"
    elif [ -d "${WINE_PATH}/share/wine/dlls/${PACKAGE_NAME}" ]; then
        dlls_path_result="${WINE_PATH}/share/wine/dlls/${PACKAGE_NAME}"
    fi
    if [ "$dlls_path_result" == "" ]; then
        return
    fi

    # 火锅9
    if echo "$WINE_PATH" | grep -q hotpot9 &>/dev/null; then
        make_app_dll_path_hotpot9
        return
    fi

    local appDllPath="${WINEPREFIX}/override-dlls"
    local flag="0"
    IFS=':'
    for dlls_path in ${dlls_path_result[@]}; do
        # 判断是否有查分包？
        array_so=($(find "$dlls_path/" -name "*.patch" | xargs))
        if [ "$array_so" == "" ]; then
            continue
        fi

        flag="1"

        # 判断是否已经解压过？
        if [ -d "$appDllPath" ]; then
            if [ -f $dlls_path/32 ]; then
                if diff "${dlls_path}/32" "${appDllPath}/32" &>/dev/null; then
                    continue
                fi
            elif [ -f $dlls_path/64 ]; then
                if diff "${dlls_path}/64" "${appDllPath}/64" &>/dev/null; then
                    continue
                fi
            fi
            remove_path "$appDllPath"
        fi
        mkdir "$appDllPath"

        OLDIFS=$IFS
        IFS=' '
        for so in ${array_so[@]}; do
            so=${so%.*}
            so_name=${so##*/}
            so_path=${so%/*}
            if [ -f $so_path/32 ]; then
                cp "${so_path}/32" "${appDllPath}/32"
                if echo "$WINE_PATH" | grep -q hotpot6 &>/dev/null; then
                    old_so=$WINE_PATH/lib/wine/$so_name
                else
                    old_so=$WINE_PATH/lib/wine/i386-unix/$so_name
                    if [ ! -f "$old_so" ]; then
                        old_so=$WINE_PATH/lib/wine/i386-windows/$so_name
                    fi
                fi
            elif [ -f $so_path/64 ]; then
                cp "${so_path}/64" "${appDllPath}/64"
                if echo "$WINE_PATH" | grep -q hotpot6 &>/dev/null; then
                    old_so=$WINE_PATH/lib64/wine/$so_name
                else
                    old_so=$WINE_PATH/lib/wine/x86_64-unix/$so_name
                    if [ ! -f "$old_so" ]; then
                        old_so=$WINE_PATH/lib/wine/x86_64-windows/$so_name
                    fi
                fi
            else
                break
            fi
            override_so="${appDllPath}/${so_name}"
            bspatch "$old_so" "$override_so" "$so.patch"
        done
        IFS=$OLDIFS
    done
    IFS=' '
    if [ "$flag" == "1" ]; then
        dlls_path_result+=":"
        dlls_path_result+="${appDllPath}"
        run_or_print export HOTPOT_APPDLLPATH="${dlls_path_result}"
        chmod -R 777 "${appDllPath}"
    elif [ "$HOTPOT_APPDLLPATH" == "" ]; then
        run_or_print export HOTPOT_APPDLLPATH="${dlls_path_result}"
        remove_path "${appDllPath}" &>/dev/null
    else
        remove_path "${appDllPath}" &>/dev/null
    fi
}

parse_config_file() {
    refreshappdetail

    PACKAGE_NAME="$(cat "$JSON_FILE" | jq -r .packagename)"
    if jq_none "$PACKAGE_NAME"; then
        return 1
    fi

    # 设置环境变量
    set_runtime_env "$@"

    # 通过差分包生成动态库
    make_app_dll_path

    # change_wine_for_arm
}

change_wine_for_arm() {
    if [ "$(uname -m)" == "aarch64" ]; then
        echo "### change for arm ###"
        if [ "$WINE_PATH" != "/opt/winux/hotpot9/usr/local" ]; then
            export WINE_PATH="/opt/winux/hotpot9/usr/local"
            run_or_print export WINE_PATH="$WINE_PATH"
            if [ "$HOTPOT_APPDLLPATH" != "" ]; then
                export HOTPOT_APPDLLPATH="${WINE_PATH}/share/wine/dlls/$(basename "$HOTPOT_APPDLLPATH")"
                run_or_print export HOTPOT_APPDLLPATH="$HOTPOT_APPDLLPATH"
            fi
        fi
    fi
}

set_runtime_env() {
    for ((i = 0; ; i++)); do
        local key=$(cat "$JSON_FILE" | jq -r .run.env[$i].key)
        if jq_none "$key"; then
            break
        fi
        if [ "$key" == "WINEARCH" ]; then
            continue
        fi
        local value=$(cat "$JSON_FILE" | jq -r .run.env[$i].value)
        run_or_print export ${key}="${value}"
        export ${key}="${value}"
    done

    if jq_none "$WINE_PATH"; then
        WINE_PATH="/opt/winux/hotpot9/usr/local/"
    fi

    # 设置环境变量
    run_or_print export WINEPREFIX="$WINEPREFIX"
    if [ "$HOTPOT_DISABLE_BOOT_WINDOW" == "" ]; then
        run_or_print export HOTPOT_DISABLE_BOOT_WINDOW="1"
    fi
    if [ "${OUTPUT_DIRECTION-NotDefine}" == "NotDefine" ]; then
        if [ "$(get_settings printWineLog)" == "true" ]; then
            OUTPUT_DIRECTION="${WINEPREFIX}/${PACKAGE_NAME}.log"
        else
            OUTPUT_DIRECTION="/dev/null"
        fi
    fi
    if [ -f "$OUTPUT_DIRECTION" ]; then
        remove_path "$OUTPUT_DIRECTION"
    fi

    # 设置专用机环境变量
    if [ "$(lsb_release -a 2>/dev/null | grep "涉密专用版")" != "" ]; then
        run_or_print export RES_OPTIONS="timeout:1 attempts:0"
        # 若环境变量NetProfm_Option为STOP则关闭netprofm
        if [ "$(echo -n $NetProfm_Option | grep "STOP")" != "" ]; then
            run_or_print export WINEDLLOVERRIDES="netprofm=d"
        fi
    fi

    # 设置专用机环境变量 hotpot-extra 中的配置策略
    if [ -f "/opt/hotpot-extra/config.json" ]; then
        while read blacklist_exe; do
            if [ "$WINEDLLOVERRIDES" != "" ]; then
                WINEDLLOVERRIDES+=";"
            fi
            WINEDLLOVERRIDES+="${blacklist_exe}=d"
        done < <(cat "/opt/hotpot-extra/config.json" | jq -r ".exeBlacklist[]")
        run_or_print export WINEDLLOVERRIDES="$WINEDLLOVERRIDES"
    fi

    # ==== 转译环境处理（ARM + 龙芯）====
    if [ "$(uname -m)" == "aarch64" ] || [ "$(uname -m)" == "loongarch64" ]; then
        # 旧 deb 兼容：无 yac 配置时，按优先级检测可用引擎
        if jq_none "$HOTPOT_TRANSLATION_ENGINE"; then
            if [ -f "/opt/phybin/bin/jiuyi" ]; then
                export HOTPOT_TRANSLATION_ENGINE="phybin"
            elif [ -f "/opt/exagear/bin/exagear" ]; then
                export HOTPOT_TRANSLATION_ENGINE="exagear"
            elif [ -f "$BOX64_BIN_PATH" ]; then
                export HOTPOT_TRANSLATION_ENGINE="box64"
                export HOTPOT_TRANSLATION_BIN="$BOX64_BIN_PATH"
            elif [ -f "/usr/bin/latx-x86_64" ]; then
                export HOTPOT_TRANSLATION_ENGINE="latx"
            fi
        fi
        # jiuyi/exagear/latx：不包装，binfmt 自动处理
        # box64：wine-link 内部自动路由（见 wine-link 第 9 节），此处不需特殊包装
    fi

    # run（所有模式统一走 wine-link，由 wine-link 做最终路由）
    RUN_COMMAND=(
        "exec"
		"$HOTPOT_WINE"
        "$@"  # 直接添加所有参数
    )
}

install_reg() {
    reg_files=()
    touch "${WINEPREFIX}/.cache"
    load_cache_vars "${WINEPREFIX}/.cache"

    # common reg
    install_template_reg="/opt/winux/yuanyanghotpot-ui/template/install_template.reg"
    if [ -f "$install_template_reg" ]; then
        install_template_reg_md5="$(md5sum "$install_template_reg" | awk '{print $1}')"
        if [ "$install_template_reg_md5" != "$cache_install_template_reg_md5" ]; then
            reg_files+=("$install_template_reg")
            if [ "$SAYZHIMAKAIMEN" == "" ]; then
                sed -i '/cache_install_template_reg_md5=/d' "${WINEPREFIX}/.cache"
                echo "cache_install_template_reg_md5=${install_template_reg_md5}" >>"${WINEPREFIX}/.cache"
            fi
        fi
    fi

    # if ! echo "$WINE_PATH" | grep -qw '/opt/winux/hotpot6/usr/local\|/opt/winux/hotpot7/usr/local\|/opt/winux/hotpot8/usr/local' && \
    #    ! grep -w -A 5 "\[Environment\]" "${WINEPREFIX}/user.reg" | grep -e "TEMP\|TMP" | grep -wq "\%USERPROFILE\%"; then
    #     rename_temp_path_reg="/opt/winux/yuanyanghotpot-ui/template/rename_temp_path.reg"
    #     if [ -f "$rename_temp_path_reg" ]; then
    #         rename_temp_path_reg_md5="$(md5sum "$rename_temp_path_reg" | awk '{print $1}')"
    #         if [ "$rename_temp_path_reg_md5" != "$cache_rename_temp_path_reg_md5" ]; then
    #             reg_files+=("$rename_temp_path_reg")
    #             if [ "$SAYZHIMAKAIMEN" == "" ]; then
    #                 sed -i '/cache_rename_temp_path_reg_md5=/d' "${WINEPREFIX}/.cache"
    #                 echo "cache_rename_temp_path_reg_md5=${rename_temp_path_reg_md5}" >>"${WINEPREFIX}/.cache"
    #             fi
    #         fi
    #     fi
    # fi

    # driveletter_without_mount
    if [ "$HOTPOT_IGNORE_INVALID_DRIVE" == "1" ]; then
        driveletter_without_mount_reg="/opt/winux/yuanyanghotpot-ui/template/ignore_driveletter_without_mount.reg"
    else
        driveletter_without_mount_reg="/opt/winux/yuanyanghotpot-ui/template/display_driveletter_without_mount.reg"
    fi
    if [ -f "$driveletter_without_mount_reg" ]; then
        driveletter_without_mount_reg_md5="$(md5sum "$driveletter_without_mount_reg" | awk '{print $1}')"
        if [ "$driveletter_without_mount_reg_md5" != "$cache_driveletter_without_mount_reg_md5" ]; then
            reg_files+=("$driveletter_without_mount_reg")
            if [ "$SAYZHIMAKAIMEN" == "" ]; then
                sed -i '/cache_driveletter_without_mount_reg_md5=/d' "${WINEPREFIX}/.cache"
                echo "cache_driveletter_without_mount_reg_md5=${driveletter_without_mount_reg_md5}" >>"${WINEPREFIX}/.cache"
            fi
        fi
    fi

    # wfonts
    wfonts_reg="/opt/winux/yuanyanghotpot-ui/template/wfonts.reg"
    if [ -d "/opt/wfonts" ]; then
        wfonts_reg_md5="$(md5sum "$wfonts_reg" | awk '{print $1}')"
        if [ "$wfonts_reg_md5" != "$cache_wfonts_reg_md5" ]; then
            reg_files+=("$wfonts_reg")
            if [ "$SAYZHIMAKAIMEN" == "" ]; then
                sed -i '/cache_wfonts_reg_md5=/d' "${WINEPREFIX}/.cache"
                echo "cache_wfonts_reg_md5=${wfonts_reg_md5}" >>"${WINEPREFIX}/.cache"
            fi
        fi
    fi

    # 更新dpi
    if type xdpyinfo &>/dev/null; then
        system_dpi=$(dimensions_to_dpi $(xdpyinfo | grep -e dimensions | awk -F ' ' '{print $2}' | awk -F 'x' '{print $2}'))
        # 1、该应用没有执行过自动设置dpi（old_system_dpi为空）
        # 2、系统分辨率变了（"$cache_system_dpi" != "$system_dpi"）
        # 3、该应用执行过一次自动设置dpi，old_system_dpi和system_dpi会相等，在没有上述1和2两个条件重新触发时，不会再次执行自动修改dpi的操作，允许用户可以手动改变dpi的设置。
        if [ "$cache_system_dpi" != "$system_dpi" ]; then
            reg_files+=("/opt/winux/yuanyanghotpot-ui/template/logpixels_${system_dpi}.reg")
        fi
    fi

    # Apply conditional registry fixes (see conditional-regs.json)
    if [ "$SAYZHIMAKAIMEN" == "" ]; then
        /opt/winux/tools/appmanager/apply-conditional-regs.sh "$WINEPREFIX"
    fi

    # app special reg
    app_reg_file="${WINEPREFIX}/${PACKAGE_NAME}.reg" # yac配置优先
    if [ ! -f "$app_reg_file" ]; then
        if [ -f "/opt/winux/hotpot-manager/regs/${PACKAGE_NAME}.reg" ]; then
            cp "/opt/winux/hotpot-manager/regs/${PACKAGE_NAME}.reg" "$app_reg_file" # 旧配置
        fi
    fi
    if [ -f "$app_reg_file" ]; then
        app_reg_file_md5="$(md5sum "$app_reg_file" | awk '{print $1}')"
        if [ "$app_reg_file_md5" != "$cache_app_reg_file_md5" ]; then
            reg_files+=("$app_reg_file")
            if [ "$SAYZHIMAKAIMEN" == "" ]; then
                sed -i '/cache_app_reg_file_md5=/d' "${WINEPREFIX}/.cache"
                echo "cache_app_reg_file_md5=${app_reg_file_md5}" >>"${WINEPREFIX}/.cache"
            fi
        fi
    fi

    # use linux fileselection
    if echo "$WINE_PATH" | grep -qw '/opt/winux/hotpot9/usr/local\|/opt/winux/hotpot10/usr/local\|/opt/winux/nfs-wine-11/usr/local'; then
        # if [ "$HOTPOT_FILESELECTION_STYLE" == "linux" ]; then
            # use_linux_fileselection_reg="/opt/winux/yuanyanghotpot-ui/template/use_linux_fileselection.reg"
        # elif [ "$HOTPOT_FILESELECTION_STYLE" == "wine" ]; then
            use_linux_fileselection_reg="/opt/winux/yuanyanghotpot-ui/template/use_wine_fileselection.reg"
        # fi
        if [ -f "$use_linux_fileselection_reg" ]; then
            use_linux_fileselection_reg_md5="$(md5sum "$use_linux_fileselection_reg" | awk '{print $1}')"
            if [ "$use_linux_fileselection_reg_md5" != "$cache_use_linux_fileselection_reg_md5" ]; then
                reg_files+=("$use_linux_fileselection_reg")
                if [ "$SAYZHIMAKAIMEN" == "" ]; then
                    sed -i '/cache_use_linux_fileselection_reg_md5=/d' "${WINEPREFIX}/.cache"
                    echo "cache_use_linux_fileselection_reg_md5=${use_linux_fileselection_reg_md5}" >>"${WINEPREFIX}/.cache"
                fi
            fi
        fi
    fi

    # 更新注册表
    if [ "${#reg_files[@]}" -gt 0 ]; then
        run_or_print 	"$HOTPOT_WINE" regedit "${reg_files[@]}"
        if [ "$?" != "0" ]; then exit; fi
        run_or_print "$HOTPOT_WINESERVER" "-kw"
        # if [ "$SAYZHIMAKAIMEN" == "" ]; then
        #     if [ -f "${WINEPREFIX}/${PACKAGE_NAME}.reg" ]; then
        #         remove_path "${WINEPREFIX}/${PACKAGE_NAME}.reg"
        #     fi
        # fi
        # 判断dpi是否设置成功
        if [ "$cache_system_dpi" != "$system_dpi" ] && (($(grep LogPixels "$WINEPREFIX"/*.reg | grep $(printf "%x" $system_dpi) | wc -l) >= 3)); then
            if [ "$SAYZHIMAKAIMEN" == "" ]; then
                sed -i '/cache_system_dpi=/d' "${WINEPREFIX}/.cache"
                echo "cache_system_dpi=${system_dpi}" >>"${WINEPREFIX}/.cache"
            fi
        fi
    fi
}

is_show_banner() {
    if ! type hotpot-assistant &>/dev/null; then
        return 1
    fi
    if [ "$HOTPOT_DISABLE_BOOT_WINDOW" != "1" ]; then
        return 1
    fi
    if [ "$(get_settings showBanner)" == "false" ]; then
        return 1
    fi
    if [ "$ACTION" == "openfile" ]; then
        return 1
    fi
    return 0
}

show_banner() {
    if ! is_show_banner; then
        run_or_print export HOTPOT_DISABLE_BOOT_WINDOW="0"
        return 1
    fi

    # 启动banner显示desktop的图标和名称
    local desktop_file="$(cat /proc/$$/environ | xargs -L 1 --null | grep -w GIO_LAUNCHED_DESKTOP_FILE | awk -F '=' '{print $2}')"
    local desktop_icon=""
    local desktop_name=""
    if [ -f "$desktop_file" ]; then
        desktop_icon="$(cat "$desktop_file" | grep -w Icon | awk -F '=' '{print $2}')"
        desktop_name="$(cat "$desktop_file" | grep -w Name | awk -F '=' '{print $2}')"
    fi
    if [ ! -f "$desktop_icon" ] || [ "$desktop_name" == "" ]; then
        run_or_print export HOTPOT_DISABLE_BOOT_WINDOW="0"
        return 1
    fi

    # 后台检测：如果应用程序的窗口出现，则关闭Banner窗口。
    (
        while true; do
            while read line; do
                local prefix_from_pid="$(yuanyanghotpot-sudoer get-prefix-from-pid "$line")"
                if [ "$prefix_from_pid" == "$WINEPREFIX" ]; then
                    exit
                fi
            done < <(wmctrl -l -p -G | awk '{print $3 " " $6 " " $7}' | grep -v " 1 1" | awk '{print $1}')
            sleep 1
        done
    ) &
    success_pid=$!

    # 后台检测：如果应用程序启动失败，则关闭Banner窗口。
    (
        local apprun="0"
        local apptimeout=0
        while true; do
            if ! yuanyanghotpot-sudoer list-run-apps | grep -q "$WINEPREFIX"; then
                apptimeout=$(expr $apptimeout + 1)
                if [ "$apprun" == "1" ]; then
                    # 如果应用启动过，并且已经失去wineserver超过2秒，则判定失败
                    if (($apptimeout >= 2)); then
                        exit
                    fi
                else
                    # 如果10秒，wineserver还没有启动过，则失败
                    if (($apptimeout >= 10)); then
                        exit
                    fi
                fi
            else
                apprun="1"
                apptimeout=0
            fi
            sleep 1
        done
    ) &
    failed_pid=$!

    # Banner超时退出：2分钟。
    (
        local banner_timeout=0
        while true; do
            banner_timeout=$(expr $banner_timeout + 1)
            sleep 1
            if (($banner_timeout >= 120)); then
                exit
            fi
        done
    ) &
    timeout_pid=$!

    # 启动Banner窗口
    (
        export WINEPREFIX=""
        hotpot-assistant starter "{\"status\":\"loading\",\"id\":\"$TIME_STAMP\",\"iconfile\":\"$desktop_icon\",\"softname\":\"$desktop_name\"}"
    ) &
    banner_pid=$!

    # 等待：关闭Banner窗口，以及清理子进程
    while true; do
        # 启动成功
        if ! is_pid_alive $success_pid; then
            pstree_kill $success_pid &>/dev/null
            pstree_kill $failed_pid &>/dev/null
            pstree_kill $timeout_pid &>/dev/null
            pstree_kill $banner_pid &>/dev/null
            exit
        fi

        # 手动关闭了窗口
        if ! is_pid_alive $banner_pid; then
            pstree_kill $success_pid &>/dev/null
            pstree_kill $failed_pid &>/dev/null
            pstree_kill $timeout_pid &>/dev/null
            pstree_kill $banner_pid &>/dev/null
            exit
        fi

        # 2分钟超时了
        if ! is_pid_alive $timeout_pid; then
            pstree_kill $success_pid &>/dev/null
            pstree_kill $failed_pid &>/dev/null
            pstree_kill $timeout_pid &>/dev/null
            pstree_kill $banner_pid &>/dev/null
            exit
        fi

        # 启动失败
        if ! is_pid_alive $failed_pid; then
            pstree_kill $success_pid &>/dev/null
            pstree_kill $failed_pid &>/dev/null
            pstree_kill $timeout_pid &>/dev/null
            # 启动Banner窗口
            (
                local log_file=""
                if [ -f "$OUTPUT_DIRECTION" ]; then
                    log_file="$OUTPUT_DIRECTION"
                fi
                hotpot-assistant starter "{\"status\":\"failed\",\"id\":\"$TIME_STAMP\",\"iconfile\":\"$desktop_icon\",\"softname\":\"$desktop_name\",\"log\":\"$log_file\",\"prefix\":\"$WINEPREFIX\",\"jsonfile\":\"$JSON_FILE\"}"
            ) &
            exit
        fi
        sleep 1
    done
}

open_file() {
    local start_file="$(readlink -f "$1")"
    local extension="${start_file##*.}"
    local filetype="$(xdg-mime query filetype "$start_file")"
    local desktop_file="$(grep -irl "$filetype" "${WINEPREFIX}/file-associations/applications/" | grep -w "wine-extension-${extension}.desktop" | sed -n 1p)"
    if [ "$desktop_file" == "" ]; then
        desktop_file="$(grep -irl "$filetype" "${WINEPREFIX}/file-associations/applications/" | sed -n 1p)"
    fi
    local prog_id=""
    local openfile_commands=(
        "exec"
        	"$HOTPOT_WINE"
        "start"
        "/ProgIDOpen"
    )

    if [ -f "$desktop_file" ]; then
        prog_id="$(cat "$desktop_file" | grep -w "Exec" | awk -F 'start /ProgIDOpen | %f' '{print $2}')"
        openfile_commands+=("$(printf "%b" "$prog_id" | xargs -i echo "{}")")
        openfile_commands+=("$start_file")
    fi

    # 没找到，退出启动
    if [ "$prog_id" == "" ]; then
        local desktop_file="$(cat /proc/$$/environ | xargs -L 1 --null | grep -w GIO_LAUNCHED_DESKTOP_FILE | awk -F '=' '{print $2}')"
        local desktop_name=""
        if [ -f "$desktop_file" ]; then
            desktop_name="$(cat "$desktop_file" | grep -w Name | awk -F '=' '{print $2}')"
        else
            desktop_name="$(cat "$JSON_FILE" | jq -r .softname)"
        fi
        if jq_none "$desktop_name"; then
            return
        fi

        if type hotpot-assistant &>/dev/null; then
            hotpot-assistant dialog "{\"type\":\"warn\",\"title\":\"${desktop_name}\",\"content\":\"${desktop_name}无法打开 ".${filetype}" 类型文件，请设置文件关联\"}"
        else
            zenity --warning --width=300 --height=30 --text="${desktop_name}无法打开 ".${filetype}" 类型文件，请设置文件关联"
        fi
        return
    fi

    # run
    (run_or_print "${openfile_commands[@]}")
}

hotpot_package_name() {
    if [ "$WINE_PATH" == "/opt/winux/hotpot6/usr/local" ]; then
        echo "hotpot6"
    elif [ "$WINE_PATH" == "/opt/winux/hotpot7/usr/local" ]; then
        echo "hotpot7"
    elif [ "$WINE_PATH" == "/opt/winux/hotpot8/usr/local" ]; then
        echo "hotpot8"
    elif [ "$WINE_PATH" == "/opt/winux/hotpot9/usr/local" ]; then
        echo "hotpot9"
    elif [ "$WINE_PATH" == "/opt/winux/hotpot10/usr/local" ]; then
        echo "hotpot10"
    elif [ "$WINE_PATH" == "/opt/winux/hotpot10-wow64/usr/local" ]; then
        echo "hotpot10-wow64"
    fi
    echo ""
}

sync_dosdevice() {
    if [ "$HOTPOT_SYNC_DOSDEVICE" == "" ]; then
        return
    fi
    touch "${WINEPREFIX}/.cache"
    load_cache_vars "${WINEPREFIX}/.cache"
    if [ "$cache_sync_dosdevice" == "1" ]; then
        return
    elif [ "$SAYZHIMAKAIMEN" != "" ]; then
        echo -e "\033[0;32msync_dosdevice\033[0m"
        return
    fi

    if [ "$("/opt/winux/tools/appmanager/cdos_computer_list" 2>/dev/null)" == "" ]; then
        return
    fi

    while read line; do
        if [ "${WINEPREFIX}" == "$(readlink -f "${line}")" ]; then
            # echo "应用运行中，请先关闭应用"
            return
        fi
    done < <(yuanyanghotpot-sudoer list-run-apps 2>/dev/null)

    cd "${WINEPREFIX}/dosdevices"
    # 删除旧设备
    while read line; do
        if [ "$line" == "c:" ] || [ "$line" == "z:" ]; then
            continue
        fi
        if [ "$line" == "d:" ] && [ "$(realpath d:)" == "${WINEPREFIX}/drive_d" ] && [ "$(ls "${WINEPREFIX}/drive_d" 2>/dev/null)" != "" ]; then
            continue
        fi
        rm "$line"
    done < <(ls 2>/dev/null)

    # 重新创建磁盘链接
    while read line; do
        eval $line
    done < <("/opt/winux/tools/appmanager/cdos_computer_list" 2>/dev/null)
    cd - &>/dev/null

    sed -i '/cache_sync_dosdevice=/d' "${WINEPREFIX}/.cache"
    echo "cache_sync_dosdevice=1" >>"${WINEPREFIX}/.cache"
}

function start_app() {
    /opt/winux/tools/appmanager/check_reg
    if [ "$?" != "0" ]; then
        return
    fi

    # chown
    touch "${WINEPREFIX}/.cache"
    load_cache_vars "${WINEPREFIX}/.cache"
    if [ "$cache_current_owner" != "$LOGNAME" ]; then
        run_or_print yuanyanghotpot-sudoer current-owner --apppath "$WINEPREFIX"
        if [ "$SAYZHIMAKAIMEN" == "" ]; then
            sed -i '/cache_current_owner=/d' "${WINEPREFIX}/.cache"
            echo "cache_current_owner=${LOGNAME}" >>"${WINEPREFIX}/.cache"
        fi
    fi

    # 拷贝用户目录
    make_special_user_dir "$LOGNAME"

    # 解析配置文件
    parse_config_file "$@"

    sync_dosdevice

    run_or_print yuanyanghotpot-sudoer install-patch --json "{\"data\":[{\"package_name\":\"${PACKAGE_NAME}\"},{\"package_name\":\"$(hotpot_package_name)\"},{\"package_name\":\"yuanyanghotpot\"},{\"package_name\":\"hotpot-assistant\"}]}" --apppath "$WINEPREFIX"

    # APP 特殊处理
    local prerun_file="${WINEPREFIX}/${PACKAGE_NAME}_prerun.sh"
    if [ ! -f "$prerun_file" ]; then
        prerun_file="/opt/winux/hotpot-manager/prerun/${PACKAGE_NAME}_prerun.sh"
    fi
    if [ -f "$prerun_file" ]; then
        if [ "$SAYZHIMAKAIMEN" != "" ]; then
            echo -e "\033[0;32msource \"$prerun_file\"\033[0m"
        fi
        source "$prerun_file"
    fi

    # pre_run 函数执行在所有wine命令之前，某些配置在启动wine之后设置就不生效了
    if [ "$(type -t pre_run)" == "function" ]; then
        run_or_print "pre_run"
        if [ "$?" != "0" ]; then # pre_run 返回非0代表停止启动
            return
        fi
    fi

    # 赋予网络权限
    local need_caps="cap_net_raw,cap_net_bind_service+eip"
    if [ "$HOTPOT_SETCAP_EIP" == "1" ]; then
        need_caps="cap_net_raw,cap_net_bind_service-eip"
    fi
    if [ "$HOTPOT_NEED_CAPS" != "" ]; then
        need_caps="$HOTPOT_NEED_CAPS"
    fi

    # 判断${WINE_PATH} 不空的情况下，才去执行
    if [ ! -z ${WINE_PATH} ]; then
      run_or_print yuanyanghotpot-sudoer setcap "${WINE_PATH}" "$need_caps"
    fi

    # 杀进程、再启动
    # 判断${WINE_PATH} 不空的情况下，才去执行
    if [ "$KILL_PROC" == "1" ] && [ -n "${WINE_PATH}" ]; then
        run_or_print "$HOTPOT_WINESERVER" "-kw"
    fi

    # 启动Banner窗口
    if [ "$SAYZHIMAKAIMEN" == "" ]; then
        show_banner &
    fi

    # 安装注册表
    install_reg

    if [ "$ACTION" == "start" ]; then
        # pre_run2 函数紧挨着应用启动命令之前执行，可以用来做最后的配置，或者一次启动多个程序．
        if [ "$(type -t pre_run2)" == "function" ]; then
            run_or_print "pre_run2"
        fi
        (run_or_print "${RUN_COMMAND[@]}")
    elif [ "$ACTION" == "openfile" ]; then
        open_file "$@"
    fi
}

if [ "$ACTION" == "start" ] || [ "$ACTION" == "openfile" ]; then
    start_app "$@"
elif [ "$ACTION" == "" ]; then
    install_app
elif [ "$ACTION" == "uninstall" ]; then
    uninstall_app
fi
