#!/bin/bash

set -u

preferCONFIGFILE="${HOME}/.config/compatible-layer/yorNcompatbleMode.ini"
baseOS=

# TO TEST
function dockerF() {
    Exec="$1"
    # 将 Exec 值转换为 md5 值，作为容器名称
    dockerContainerName=$(echo -n "$Exec$baseOS" | md5sum | awk '{print $1}')
    echo "DEBUG - "$Exec$baseOS"对应的容器名称为:$dockerContainerName" >>$logFile

    # 判断容器是否存在
    replyValue=$(dbus-send --system --type=method_call --print-reply \
        --dest=com.kylin.dockerAgent /com/kylin/dockerAgent com.kylin.dockerAgent.dockerAgentInspect \
        string:"$dockerContainerName")
    replyValue=$(echo $replyValue | awk -F " " '{ print $NF }')
    if [ $replyValue -eq 0 ]; then
        echo "DEBUG - 容器存在" >>$logFile
        # 启动容器
        replyValue=$(dbus-send --system --type=method_call --print-reply \
            --dest=com.kylin.dockerAgent /com/kylin/dockerAgent com.kylin.dockerAgent.dockerAgentRun \
            string:"$dockerContainerName" string:"$Exec")
        replyValue=$(echo $replyValue | awk -F " " '{ print $NF }')
        if [ $replyValue -eq 0 ]; then
            echo "DEBUG - $Exec启动成功" >>$logFile
            exit 0
        else
            echo "ERROR - $Exec启动失败:$replyValue，已存在容器将被删除..." >>$logFile
            replyValue=$(dbus-send --system --type=method_call --print-reply \
                --dest=com.kylin.dockerAgent /com/kylin/dockerAgent com.kylin.dockerAgent.dockerAgentRm \
                string:"$dockerContainerName")
            replyValue=$(echo $replyValue | awk -F " " '{ print $NF }')
            if [ $replyValue -eq 0 ]; then
                echo "DEBUG - 容器成功删除，重新创建容器并启动应用" >>$logFile
            else
                echo "ERROR - 容器删除失败:$replyValue，程序退出" >>$logFile
                exit -1
            fi
        fi
    else
        # -2：容器不存在 -1：dbus执行失败 -404：dbus执行超时
        echo "DEBUG - 容器不存在：$replyValue，创建容器并启动应用" >>$logFile 2>&1
    fi

    # 遍历，确定兼容需要挂载的 fs.old 目录
    mntDirOld=''
    fsold="/$2"
    aidList=("/bin" "/etc" "/lib" "/lib64" "/lib32" "/opt" "/sbin" "/usr" "/var")
    # otherList=("/backup" "/cdrom" "/box" "/lost+found" "/run" "/sys" "/data" "/home" "/media" "/proc" "/tmp" "/boot" "/dev" "/mnt" "/root" "/srv" "/run")
    for eachFsOld in "$fsold"/*; do
        # 过滤非目录和链接目录
        if [ ! -d "$eachFsOld" ]; then
            continue
        fi
        # 过滤前缀
        eachFsOld=$(echo "${eachFsOld}" | sed "s/^\/$2//")
        for eachAidList in ${aidList[@]}; do
            # echo $eachAidList
            if [ $eachAidList == $eachFsOld ]; then
                mntDirOld=$mntDirOld" -v $fsold$eachFsOld:$eachFsOld"
                break
            fi
        done
    done

    # 遍历，确定兼容需要挂载的 host 目录
    # aidListHost=("/dev" "/home" "/media" "/mnt" "/tmp" "/data")
    otherListHost=("/backup" "/cdrom" "/lost+found" "/run" "/sys" "/fs.old" "/usr" "/opt" "/proc" "/boot" "/etc" "/root" "/srv" "/var" "/bin" "/lib" "/lib64" "/lib32" "/sbin" "/kare-")
    mntDirHost=""
    for eachR in /*; do
        # 过滤非目录和链接目录
        if [ ! -d "$eachR" ]; then
            continue
        fi
        # 开始比较
        # for eachAidListHost in ${aidListHost[@]}
        # do
        #     # echo $eachAidList
        #     if [ $eachAidListHost == $eachR ]; then
        #         mntDirHost=$mntDirHost" -v $eachR:$eachR"
        #         break
        #     fi
        # done
        if [ $eachR == "/dev" ]; then
            mntDirHost=$mntDirHost" -v $eachR:$eachR"
        elif [ $eachR == "/home" ]; then
            mntDirHost=$mntDirHost" -v $eachR:$eachR"
        elif [ $eachR == "/media" ]; then
            mntDirHost=$mntDirHost" -v $eachR:$eachR"
        elif [ $eachR == "/mnt" ]; then
            mntDirHost=$mntDirHost" -v $eachR:$eachR"
        elif [ $eachR == "/tmp" ]; then
            mntDirHost=$mntDirHost" -v $eachR:$eachR"
        elif [ $eachR == "/data" ]; then
            mntDirHost=$mntDirHost" -v $eachR:$eachR"
        # 输入法需要
        elif [ $eachR == "/run" ]; then
            mntDirHost=$mntDirHost" -v $eachR:$eachR"
        # 必要目录挂载完毕，寻找是否有自建目录
        else
            flag=0
            for eachOtherListHost in ${otherListHost[@]}; do
                if [[ $eachR == $eachOtherListHost* ]]; then
                    flag=1
                    break
                else
                    flag=0
                    continue
                fi
            done
            if [ $flag -eq 0 ]; then
                echo "找到用户自建目录: $eachR" >>$logFile 2>&1
                mntDirHost=$mntDirHost" -v $eachR:$eachR"
            fi
        fi
    done
    mntDir=$mntDirOld$mntDirHost

    # docker环境变量
    dockerEnv='-e DBUS_SESSION_BUS_ADDRESS="$DBUS_SESSION_BUS_ADDRESS" -e QT_X11_NO_MITSHM=1'

    # docker特殊参数
    specialParam=""

    # docker登录用户
    dockerUser=$(id -u)

    dockerIsoName="$3"

    replyValue=$(dbus-send --system --type=method_call --print-reply \
        --dest=com.kylin.dockerAgent /com/kylin/dockerAgent com.kylin.dockerAgent.dockerAgentCreate \
        string:"$dockerUser" string:"$dockerContainerName" string:"$dockerEnv" string:"$mntDir" string:"$dockerIsoName")
    replyValue=$(echo $replyValue | awk -F " " '{ print $NF }')
    if [ $replyValue -eq 0 ]; then
        echo "DEBUG - $Exec对应的容器$dockerContainerName创建成功" >>$logFile
    else
        echo "ERROR - $Exec对应的容器$dockerContainerName创建失败:$replyValue" >>$logFile
        exit -1
    fi
    replyValue=$(dbus-send --system --type=method_call --print-reply \
        --dest=com.kylin.dockerAgent /com/kylin/dockerAgent com.kylin.dockerAgent.dockerAgentStart \
        string:"$dockerContainerName")
    replyValue=$(echo $replyValue | awk -F " " '{ print $NF }')
    if [ $replyValue -eq 0 ]; then
        echo "DEBUG - $Exec对应的容器$dockerContainerName启动成功" >>$logFile
    else
        echo "ERROR - $Exec对应的容器$dockerContainerName启动失败:$replyValue" >>$logFile
        exit -1
    fi
    replyValue=$(dbus-send --system --type=method_call --print-reply \
        --dest=com.kylin.dockerAgent /com/kylin/dockerAgent com.kylin.dockerAgent.dockerAgentRun \
        string:"$dockerContainerName" string:"$Exec")
    replyValue=$(echo $replyValue | awk -F " " '{ print $NF }')
    if [ $replyValue -eq 0 ]; then
        echo "DEBUG - $Exec启动成功" >>$logFile
    else
        echo "ERROR - $Exec启动失败:$replyValue" >>$logFile
        exit -1
    fi
}

function bwrapF() {
    Exec="$1"
    mntDirOld=''
    fsold="/$2"
    aidList=("/bin" "/etc" "/lib" "/lib64" "/lib32" "/opt" "/sbin" "/usr" "/var")
    # otherList=("/backup" "/cdrom" "/box" "/lost+found" "/run" "/sys" "/data" "/home" "/media" "/proc" "/tmp" "/boot" "/dev" "/mnt" "/root" "/srv" "/run")
    for eachFsOld in "$fsold"/*; do
        # 过滤非目录和链接目录
        if [ ! -d "$eachFsOld" ]; then
            continue
        fi
        # 过滤前缀
        eachFsOld=$(echo "${eachFsOld}" | sed "s/^\/$2//")
        for eachAidList in ${aidList[@]}; do
            # echo $eachAidList
            if [ $eachAidList == $eachFsOld ]; then
                mntDirOld=$mntDirOld" --bind $fsold$eachFsOld $eachFsOld"
                continue
            fi
        done
    done
    # aidListHost=("/dev" "/home" "/media" "/mnt" "/tmp" "/data" "/run" "/sys")
    otherListHost=("/backup" "/cdrom" "/lost+found" "/fs.old" "/usr" "/opt" "/proc" "/boot" "/etc" "/root" "/srv" "/var" "/bin" "/lib" "/lib64" "/lib32" "/sbin" "/kare-")
    mntDirHost=""
    for eachR in /*; do
        # 过滤非目录和链接目录
        if [ ! -d "$eachR" ]; then
            continue
        fi
        # 开始比较
        # for eachAidListHost in ${aidListHost[@]}
        # do
        #     # echo $eachAidList
        #     if [ $eachAidListHost == $eachR ]; then
        #         mntDirHost=$mntDirHost" -v $eachR:$eachR"
        #         break
        #     fi
        # done
        if [ $eachR == "/dev" ]; then
            mntDirHost=$mntDirHost" --dev-bind $eachR $eachR"
        elif [ $eachR == "/home" ]; then
            mntDirHost=$mntDirHost" --bind $eachR $eachR"
        elif [ $eachR == "/media" ]; then
            mntDirHost=$mntDirHost" --bind $eachR $eachR"
        elif [ $eachR == "/mnt" ]; then
            mntDirHost=$mntDirHost" --bind $eachR $eachR"
        elif [ $eachR == "/tmp" ]; then
            mntDirHost=$mntDirHost" --bind $eachR $eachR"
        elif [ $eachR == "/data" ]; then
            mntDirHost=$mntDirHost" --bind $eachR $eachR"
        elif [ $eachR == "/run" ]; then
            mntDirHost=$mntDirHost" --bind $eachR $eachR"
        elif [ $eachR == "/sys" ]; then
            mntDirHost=$mntDirHost" --bind $eachR $eachR"
        # 必要目录挂载完毕，寻找是否有自建目录
        else
            flag=0
            for eachOtherListHost in ${otherListHost[@]}; do
                if [[ $eachR == $eachOtherListHost* ]]; then
                    flag=1
                    break
                else
                    flag=0
                    continue
                fi
            done
            if [ $flag -eq 0 ]; then
                echo "DEBUG - 找到用户自建目录: $eachR" >>$logFile
                mntDirHost=$mntDirHost" --bind $eachR $eachR"
            fi
        fi
    done
    mntDir=$mntDirOld$mntDirHost

    # 登录用户
    dockerUser=$(id -u)
    # 登录用户组
    dockerUserGroup=$(id -g)
    # 启动命令
    launchShell="/usr/bin/bwrap --uid $dockerUser --gid $dockerUserGroup $mntDir --proc /proc --setenv DISPLAY :0 "$Exec""
    echo "DEBUG - bwarp启动命令: $launchShell" >>$logFile
    # 启动
    $launchShell 2>&1 | tee -a "$logFile"
    pipestatus=("${PIPESTATUS[@]}")
    if [ "${pipestatus[0]}" -eq 0 ]; then
        echo "DEBUG - $Exec启动成功" >>$logFile
    else
        echo "ERROR - $Exec启动失败" >>$logFile
    fi
}

function main() {
    # 通用部分
    logDir=$HOME/.log/compatibility_layer
    logFile=$logDir/runWithCompatibility.log

    if [ ! -d $logDir ]; then
        mkdir -p $logDir
        touch $logFile
    elif [ ! -f $logFile ]; then
        touch $logFile
    fi

    echo $(date) >>$logFile

    compatibility_tool="bwrap"
    # 读取兼容层GSetings组件值，获取兼容方法
    gsettings list-schemas | grep "org.kylin.compatible-layer" >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        echo "WARNING - 内存中不存在兼容层GSetings配置文件" >>$logFile
    else
        compatibility_tool=$(gsettings get "org.kylin.compatible-layer" method 2>>$logFile)
        if [ $? -ne 0 ]; then
            echo "WARNING - 兼容层GSetings方法获取失败，使用 默认值bwrap" >>$logFile
            compatibility_tool="bwrap"
        else
            compatibility_tool=$(echo "$compatibility_tool" | sed 's/'"'"'//g' 2>>$logFile)
        fi
    fi

    recevParam="$@"
    Exec=
    if [ $(echo $recevParam | awk '{print $NF}') != "rightclick" ]; then
        Exec="$@"
        Exec=${Exec%% \%[a-zA-Z]}
        execKernal=${Exec##*/}
        gateFlag="no"
        [ -f "$preferCONFIGFILE" ] && gateFlag=$(configtool_kare "get" $preferCONFIGFILE "Gate" $execKernal)
        if [ "$gateFlag" == "no" ] || [ -z "$gateFlag" ]; then
            echo "DEBUG - 不兼容模式" >>$logFile
            $Exec >>$logFile 2>&1
            [ $? -ne 0 ] && echo "ERROR - 以不兼容模式打开失败" | tee -a $logFile
            exit 0
        else
            echo "DEBUG - 兼容模式" >>$logFile
            baseOS=$(configtool_kare "get" $preferCONFIGFILE "Env" $execKernal)
        fi
    else
        execTmp1=${recevParam%"rightclick"}
        baseOS=$(echo $execTmp1 | awk '{print $NF}')
        Exec=${execTmp1//$baseOS/}
        Exec=$(echo $Exec | sed -E 's/%[a-zA-Z]//g')
    fi
    ENVDIR="fs.old-v10"
    dockerImg="fsimage_v10"
    case ${baseOS,,} in
    ubuntu16.04)
        ENVDIR="fs.old-u16"
        dockerImg="fsimage_u16"
        ;;
    ubuntu18.04)
        ENVDIR="fs.old-u18"
        dockerImg="fsimage_u18"
        ;;
    ubuntu20.04)
        ENVDIR="fs.old-u20"
        dockerImg="fsimage_u20"
        ;;
    ubuntu22.04)
        ENVDIR="fs.old-u22"
        dockerImg="fsimage_u22"
        ;;
    openkylin1.0)
        ENVDIR="fs.old-ok1"
        dockerImg="fsimage_ok1"
        ;;
    openkylin2.0)
        ENVDIR="fs.old-ok2"
        dockerImg="fsimage_ok2"
        ;;
    v4)
        ENVDIR="fs.old-v4"
        dockerImg="fsimage_v4"
        ;;
    v10)
        ENVDIR="fs.old-v10"
        dockerImg="fsimage_v10"
        ;;
    v10sp1)
        ENVDIR="fs.old-v10sp1"
        dockerImg="fsimage_v10sp1"
        ;;
    *)
        ENVDIR="fs.old-v10"
        dockerImg="fsimage_v10"
        ;;
    esac

    if [ "$compatibility_tool" == "bwrap" ]; then
        echo "DEBUG - 兼容方案选择bwrap" >>$logFile
        echo "DEBUG - Exec: $Exec" >>$logFile
        echo "DEBUG - ENVDIR: $ENVDIR" >>$logFile
        bwrapF "$Exec" "$ENVDIR"
    elif [ "$compatibility_tool" == "docker" ]; then
        echo "DEBUG - 兼容方案选择docker" >>$logFile
        echo "DEBUG - Exec: $Exec" >>$logFile
        echo "DEBUG - ENVDIR: $ENVDIR" >>$logFile
        echo "DEBUG - dockerImg: $dockerImg" >>$logFile
        dockerF "$Exec" "$ENVDIR" "$dockerImg"
    else
        echo "ERROR - 兼容方案选择不正确,可选方案是bwrap|docker,当前方案为:$compatibility_tool" >>$logFile
    fi

    echo -e "\n\n\n" >>$logFile
}

main "$@"
