#!/bin/bash

set -u

logDir=/opt/compatibility_layer/logs
logFile=$logDir/buildCompatibilityEnv.log

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

vpWS="/opt/compatibility_layer/vpws"
vpControlFile="/opt/compatibility_layer/vpws/vp/DEBIAN/control"
vpPostRmFile="/opt/compatibility_layer/vpws/vp/DEBIAN/postrm"

echo $(date) >$logFile
echo -e "DEBUG - buildCompatibilityEnv 开始执行\n\n" >>$logFile

configDir=/opt/compatibility_layer/config
configFile=$configDir/configure.ini
installList=$configDir/install.list

if [ ! -d $configDir ]; then
    mkdir -m 755 -p $configDir
    touch $configFile $installList
    chmod 664 $configFile $installList
elif [ ! -f $configFile ]; then
    touch $configFile
    chmod 664 $configFile
elif [ ! -f $installList ]; then
    touch $installList
    chmod 664 $installList
fi

function vpManager() {
    pkgName="$1""-kare"
    karePkgName="$1"
    pkgVersion="$2"
    archValue="$3"
    [ ! -d $vpWS ] && mkdir -p $vpWS/vp/DEBIAN
    if [ ! -f $vpControlFile -o ! -f $vpPostRmFile ]; then
        echo "WARNING - VP File Not Exists" >>$logFile
        echo -e 'Package: 
Version: 
Architecture: 
Maintainer: zhanglin <zhanglin@kylinos.cn>
Installed-Size: 160
Depends: kare
Section: misc
Priority: optional
Description: virtual package.' >$vpControlFile

        echo -e '#!/bin/bash

pkgName=
pkgVersion=

if kare -l | grep "$pkgName" | grep -q "$pkgVersion"; then
    kare -r "$pkgName" "$pkgVersion"
fi' >$vpPostRmFile
        chmod a+x $vpPostRmFile
    fi
    sed -i "s/^Package:.*/Package: $pkgName/" $vpControlFile
    sed -i "s/^Version:.*/Version: $pkgVersion/" $vpControlFile
    sed -i "s/^Architecture:.*/Architecture: $archValue/" $vpControlFile
    sed -i "s/^Depends:.*/Depends: kare/" $vpControlFile
    sed -i "s/pkgName=.*/pkgName=$karePkgName/" $vpPostRmFile
    sed -i "s/pkgVersion=.*/pkgVersion=$pkgVersion/" $vpPostRmFile
    cd $vpWS && dpkg -b "vp" "${pkgName}_${pkgVersion}_${archValue}.deb"
    if [ $? -eq 0 ]; then
        if ! (fuser /var/lib/dpkg/lock-frontend && fuser /var/lib/dpkg/lock) >/dev/null 2>&1; then
            dpkg -i --force-overwrite ${pkgName}_${pkgVersion}_${archValue}.deb
        else
            count=120
            while (fuser /var/lib/dpkg/lock-frontend || fuser /var/lib/dpkg/lock); do
                echo "dpkg被占用,正在等待获取缓存锁...最长等待剩余时间${count}s" | tee -a $logFile
                sleep 1
                ((count--))
                [ $count -le 0 ] && break
            done
            dpkg -i --force-overwrite ${pkgName}_${pkgVersion}_${archValue}.deb
        fi
    else
        echo "ERROR - 虚包打包失败" | tee -a $logFile
        return -1
    fi
    # [ $? -eq 0 ] && apt -f install "./${pkgName}_${pkgVersion}_${archValue}.deb"
    [ $? -ne 0 ] && echo "ERROR - VP Config Failed" >>$logFile
    cd - >/dev/null
    ls $vpWS/vp/usr/share/applications/ | grep -q desktop && rm $vpWS/vp/usr/share/applications/*.desktop
    for x in $vpWS/vp/*; do
        if [ $x != "$vpWS/vp/DEBIAN" -a $x != "$vpWS/vp/usr" ]; then
            rm -rf $x
        fi
    done
    for x in $vpWS/vp/DEBIAN/*; do
        if [ $x != "$vpWS/vp/DEBIAN/control" -a $x != "$vpWS/vp/DEBIAN/postrm" ]; then
            rm -rf $x
        fi
    done
    for x in $vpWS/vp/usr/*; do
        if [ $x != "$vpWS/vp/usr/share" ]; then
            rm -rf $x
        fi
    done
    for x in $vpWS/vp/usr/share/*; do
        if [ $x != "$vpWS/vp/usr/share/applications" ]; then
            rm -rf $x
        fi
    done
}

function upgradeFun() {
    echo "DEBUG - 升级场景" >>$logFile
    # 内存载入兼容层GSettings组件
    echo -e "DEBUG - 内存载入兼容层GSettings配置文件" >>$logFile
    glib-compile-schemas /usr/share/glib-2.0/schemas/ >>$logFile 2>&1
    if [ $? -ne 0 ]; then
        echo "ERROR - 内存载入兼容层GSettings配置文件失败" >>$logFile
    else
        echo "DEBUG - 内存载入兼容层GSettings配置文件成功" >>$logFile
    fi

    # docker相关
    # 创建docker工作空间
    echo -e "\n\nDEBUG - 创建容器镜像空间" >>$logFile
    resourcePre="fs.old-"
    resourceList=$(find / -maxdepth 1 -type d -name "$resourcePre*")

    [ -z "$resourceList" ] && echo "DEBUG - 不存在基础环境目录,程序退出" | tee -a $logFile && exit 0

    for resourceDir in $resourceList; do
        resourcePost=${resourceDir##*-}
        docker_ws=/opt/compatibility_layer/image_upgrade
        [ "$resourcePost" = "/fs.old" ] || [ -z "$resourcePost" ] && resourcePost="v10"
        docker_ws+="$resourcePost"

        if [ -d $docker_ws ]; then
            rm -rf $docker_ws/*
        else
            mkdir -p $docker_ws
        fi
        # 创建Dockerfile文件
        echo "DEBUG - 创建Dockerfile文件" >>$logFile
        echo "FROM scratch" >$docker_ws/Dockerfile

        # 补充Dockerfile文件 - 环境变量
        echo -e "ENV  DISPLAY=:0 \\ \n\t LANG=zh_CN.UTF-8 \\ \n\t GTK_IM_MODULE=fcitx \\ \n\t QT4_IM_MODULE=fcitx \\
     \t XMODIFIERS=@im=fcitx \\ \n\t CLUTTER_IM_MODULE=fcitx \\ \n\t QT_IM_MODULE=fcitx" >>$docker_ws/Dockerfile

        # 补充Dockerfile文件 - 其他信息
        echo "USER 1000" >>$docker_ws/Dockerfile
        echo 'CMD ["/bin/bash"]' >>$docker_ws/Dockerfile

        # 构建Docker镜像
        dockerIsoName="fsimage_""$resourcePost"

        echo "DEBUG - 开始制作Docker镜像$dockerIsoName..." >>$logFile
        docker build -t $dockerIsoName $docker_ws >>$logFile 2>&1
        if [ $? -eq 0 ]; then
            echo "DEBUG - $dockerIsoName镜像构建成功" >>$logFile
        else
            echo "ERROR - $dockerIsoName镜像构建失败" >>$logFile
        fi
    done

    scriptName="kare run"
    echo -e "\n\nDEBUG - 开始修改Desktop文件..." >>$logFile
    desktopFileList=""
    for eachSubDir in $resourceList; do
        desktopFileList="${desktopFileList}${eachSubDir}/var/cache/RevisionsManager/package-desktop.info "
    done
    desktopFileList="${desktopFileList}/usr/share/kylin-os-manager/replacement/package-desktop.info"
    desktopDirDest='/opt/compatibility_layer/vpws/vp/usr/share/applications'
    for desktopFile in $desktopFileList; do
        if [ -f "$desktopFile" ]; then
            echo "DEBUG - 开始扫描Desktop文件..." >>$logFile

            cat $desktopFile | while read line; do

                read pkgInfo desktopInfo < <(echo $line | awk -F": " '{print $1,$2}')
                read pkgName pkgVersion pkgArch < <(echo $pkgInfo | awk -F"_" '{print $1,$2,$3}')
                if [ "${pkgArch}" == "x86" ]; then
                    pkgArch="amd64"
                elif ["${pkgArch}" == "mips64el"]; then
                    pkgArch="mips64el"
                else
                    pkgArch="arm64"
                fi
                vpFlag=false
                modifyFlag=true
                for eachSubDesktop in $desktopInfo; do
                    result=$(find /home/*/桌面 /usr/share/applications /etc -type f -name "$eachSubDesktop" 2>>$logFile)
                    if [ -z "${result}" ]; then
                        echo "WARNING - ${eachSubDesktop}在新系统中不存在" >>$logFile
                        continue
                    fi
                    oneOfResult=
                    for eachReault in $result; do
                        echo "DEBUG - 开始处理目标子文件 $eachReault" >>$logFile
                        # 判断是否是软链接，如果是，则跳过该子文件
                        if [ -L "$eachReault" ]; then
                            echo "WARNING - 子文件 $eachReault 是软链接文件，跳过该文件" >>$logFile
                            continue
                        fi
                        # 判断查找到的内容是否合法
                        if [[ $eachReault != *"desktop" ]]; then
                            echo "WARNING - 子文件 $eachReault 不合法，跳过该文件" >>$logFile
                            continue
                        fi
                        oneOfResult="${eachReault}"

                        execSegment=$(grep -m 1 '^Exec=' ${eachReault} | sed 's/^Exec=//')
                        if [[ "${execSegment}" =~ "KARE" ]]; then
                            echo "DEBUG -  子文件 $eachReault 已被更改，本次不做修改" >>$logFile
                            modifyFlag=false
                            continue
                        fi
                        modifyFlag=true
                        execOption=$(echo $execSegment | egrep -o "(--.*|%[a-zA-Z])")
                        placeholder=$(echo $execSegment | egrep -o "%[a-zA-Z]")
                        execTmp1=$(echo $execSegment | sed -r 's/^(\/usr\/bin\/bash |\/bin\/bash |bash |sh |\/bin\/sh |\/usr\/bin\/sh )//')
                        execTmp2=${execTmp1% \%[a-zA-Z]}
                        execOriginKernelAndParam=${execTmp2}
                        execCmd=${execTmp2%% *}

                        execAidDir="/usr/bin"
                        if [[ "${execCmd}" != "/"* ]]; then
                            execCmd="/usr/bin/$execCmd"
                        else
                            execAidDir=${execCmd%/*}
                        fi

                        [ -f "$execCmd" ] && [ "$execCmd" != "/usr/bin/kare" ] && mv "${execCmd}" "${execCmd}_OLD"

                        if [ ! -d "${vpWS}/vp${execAidDir}" ]; then
                            mkdir -p ${vpWS}/vp${execAidDir}
                        fi
                        touch ${vpWS}/vp${execCmd}_BAK
                        chmod a+x ${vpWS}/vp${execCmd}_BAK
                        touch ${vpWS}/vp${execCmd}_KAREBAK
                        chmod a+x ${vpWS}/vp${execCmd}_KAREBAK
                        if [ ! -z "${placeholder}" ]; then
                            echo "${execOriginKernelAndParam} \$@" >${vpWS}/vp${execCmd}_BAK
                            echo "${scriptName} ${execOriginKernelAndParam} \$@" >${vpWS}/vp${execCmd}_KAREBAK
                        else
                            echo "${execOriginKernelAndParam}" >${vpWS}/vp${execCmd}_BAK
                            echo "${scriptName} ${execOriginKernelAndParam}" >${vpWS}/vp${execCmd}_KAREBAK
                        fi
                        cp -fp ${vpWS}/vp${execCmd}_BAK ${vpWS}/vp${execCmd}KARE
                        sed -i "1,/^Exec=/{s|^Exec=|#Exec=|}" $eachReault
                        sed -i "/#Exec=/a\Exec=${execCmd}KARE ${placeholder}" $eachReault
                        sed -i "s|^DBusActivatable=true|#DBusActivatable=true|" $eachReault
                        # sed -i "s|^Exec=.*|Exec=${execCmd}KARE|g" $eachReault
                        break
                    done
                    [ ! -z "$oneOfResult" ] && [ -f "$oneOfResult" ] && cp -f $oneOfResult $desktopDirDest && vpFlag=true
                done
                if ${vpFlag} && ${modifyFlag}; then
                    vpManager "$pkgName" "$pkgVersion" "$pkgArch"
                else
                    echo "ERROR - 未产生虚包" >>$logFile
                fi
            done
        else
            echo "ERROR - $desktopFile 文件路径不存在" >>$logFile
        fi
    done

    echo "DEBUG - 开始迁移原系统中的服务" >>$logFile

    for resourceDir in $resourceList; do

        serviceSrcDir="$resourceDir/usr/share/dbus-1/services"
        serviceDstDir="/usr/share/dbus-1/services"
        serviceRootDir="/opt/compatibility_layer/services/"

        resourcePost=${resourceDir##*-}
        [ "$resourcePost" = "/fs.old" ] || [ -z "$resourcePost" ] && resourcePost="v10"
        serviceSubDir="${serviceRootDir}${resourcePost}"

        echo "DEBUG - 服务迁移目录为$serviceSubDir" >>$logFile

        if [ -d $serviceSubDir ]; then
            rm -rf $serviceSubDir/*
        else
            mkdir -p $serviceSubDir
        fi

        [ -d "$serviceSrcDir" ] && ls $serviceSrcDir >${serviceRootDir}services-${resourcePost}transfer.list

        if [ -f ${serviceRootDir}services-${resourcePost}.list ] && [ -f ${serviceRootDir}services-${resourcePost}transfer.list ]; then
            diff ${serviceRootDir}services-${resourcePost}.list ${serviceRootDir}services-${resourcePost}transfer.list |
                awk -F "> " '/^> /{print $2}' | while read eachSrv; do
                echo "DEBUG - 迁移服务$eachSrv" >>$logFile
                if [ -f $serviceSrcDir/$eachSrv ]; then
                    cp -p $serviceSrcDir/$eachSrv $serviceSubDir/$eachSrv
                    if [ $? -ne 0 ]; then
                        echo "ERROR - $serviceSrcDir/$eachSrv迁移失败" >>$logFile
                        continue
                    fi
                    sed -i "s|^Exec=|Exec=$scriptName |" $serviceSubDir/$eachSrv >>$logFile 2>&1
                    cp -p $serviceSubDir/$eachSrv $serviceDstDir/$eachSrv
                    if [ $? -ne 0 ]; then
                        echo "ERROR - $serviceSrcDir/$eachSrv迁移失败" >>$logFile
                        continue
                    fi
                else
                    echo "ERROR - 服务文件${serviceSrcDir}/${eachSrv}不存在,无法迁移旧系统服务，对于少部分应用存在影响" >>$logFile
                fi
            done
        else
            echo "ERROR - 服务列表不存在，无法迁移旧系统服务，对于少部分应用存在影响" >>$logFile
        fi
    done
    echo "DEBUG - 迁移原系统中的服务完成" >>$logFile
}

function nonUpgradeFun() {
    echo "DEBUG - 非升级场景" >>$logFile
    # 检测系统版本 v10 v10sp1 v11
    systemVersion=$(cat /etc/os-release | grep -i PROJECT_CODENAME | awk -F= '{print $2}')
    echo "DEBUG - 宿主机系统版本是: "$systemVersion >>$logFile

    # 制作相应系统版本的 OCI image
    # 创建docker工作空间
    echo "DEBUG - 创建工作空间" >>$logFile

    resourcePre="kare-"
    resourceList=$(find / -maxdepth 1 -type d -name "$resourcePre*")
    echo $resourceList

    [ -z "$resourceList" ] && echo "DEBUG - 不存在基础环境目录,程序退出" | tee -a $logFile && exit 0

    for resourceDir in $resourceList; do
        resourcePost=${resourceDir##*-}
        docker_ws=/opt/compatibility_layer/image
        docker_ws+="$resourcePost"
        if [ -d $docker_ws ]; then
            rm -rf $docker_ws/*
        else
            mkdir -p $docker_ws
        fi
        # 创建Dockerfile文件
        echo "DEBUG - 创建Dockerfile文件" >>$logFile
        echo "FROM scratch" >$docker_ws/Dockerfile
        echo "DEBUG - Dockerfile文件路径为: $docker_ws/Dockerfile" >>$logFile

        # 补充Dockerfile文件 - 环境变量
        echo -e "ENV  DISPLAY=:0 \\ \n\t LANG=zh_CN.UTF-8 \\ \n\t GTK_IM_MODULE=fcitx \\ \n\t QT4_IM_MODULE=fcitx \\
 \t XMODIFIERS=@im=fcitx \\ \n\t CLUTTER_IM_MODULE=fcitx \\ \n\t QT_IM_MODULE=fcitx" >>$docker_ws/Dockerfile

        # 补充工作空间资源 - v10、v10 sp1在某个路径中寻找资源目录
        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 $resourceDir/*; do
            if [ ! -d "$eachFsOld" ]; then
                continue
            fi
            # 过滤前缀
            eachFs=${eachFsOld#*${resourceDir}}
            for eachAidList in ${aidList[@]}; do
                if [ $eachAidList == $eachFs ]; then
                    echo "COPY $eachFs $eachFs" >>$docker_ws/Dockerfile
                    # p保留权限
                    cp -rp $eachFsOld $docker_ws
                    break
                fi
            done
        done

        # 补充Dockerfile文件 - 其他信息
        echo "USER 1000" >>$docker_ws/Dockerfile
        echo 'CMD ["/sbin/init"]' >>$docker_ws/Dockerfile

        # 构建OCI镜像
        dockerIsoName="baseimage_"$resourcePost
        # systemVersion=${systemVersion,,}
        # if [ "$systemVersion" == "v10sp1" ]; then
        #     # 在sp1机器上使用，构建的应该是v10的镜像
        #     dockerIsoName="baseimage_v10"
        # elif [ "$systemVersion" == "v11" ]; then
        #     # 在v11机器上使用，构建的可能是v10sp1 v10 v11镜像三者之一
        #     echo "TODO"
        # fi
        echo "DEBUG - OCI镜像名称为: $dockerIsoName" >>$logFile
        echo "DEBUG - 开始制作 OCI 镜像" >>$logFile
        docker build -t $dockerIsoName $docker_ws >>$logFile 2>&1
        if [ $? -eq 0 ]; then
            echo "DEBUG - OCI镜像构建成功" >>$logFile
        else
            echo "ERROR - OCI镜像构建失败" >>$logFile
        fi
    done
}

function main() {
    scene="$@"
    if [ $# -eq 0 ]; then
        scene="upgrade"
    fi
    if [ $scene != "upgrade" ]; then
        configtool_kare "set" $configFile "Scene" "upgrade" "no"
        nonUpgradeFun
    else
        configtool_kare "set" $configFile "Scene" "upgrade" "yes"
        upgradeFun
    fi
}

main "$@"
