#!/bin/bash

######################################################################
# vim: set ts=4 sts=4 sw=4 expandtab:
# @author      : yetist (yetist@yetipc)
# @file        : a
# @created     : 星期六 11月 19, 2022 10:51:30 CST
#
# @description :
######################################################################
#set -x

APP_TOP_DIR="/opt/wine-apps"
WINE_DIR_PREFIX="/opt/wine"
FAKE_USER="@current_user@"

# App 名称
APP_NAME=$(basename $0)
# App 中文名称
APP_NAME_CN=""
# App 版本号
APP_VERSION="1.0"
# App 压缩包文件名
APP_ARCHIVE=""
# App 升级时需要忽略的文件列表
APP_IGNORE=""
# App 运行时需要进入的路径
APP_RUN_PATH=""
# App 运行命令
APP_RUN_CMD=""
# App 运行时使用的 wine 版本号
APP_RUN_WINE=""

OPT_RESET=n
OPT_HELP=n
OPT_DEBUG=n

APP_DIR=$APP_TOP_DIR/$APP_NAME
WINEPREDLL="$APP_DIR/lib"

if [ -f $APP_DIR/$APP_NAME.metainfo ]; then
    source $APP_DIR/$APP_NAME.metainfo
else
    zenity --error --title="出错啦！" --text="找不到 $APP_DIR/$APP_NAME.metainfo 文件，请检查安装包是否正确"
    exit
fi


if [ "x$APP_RUN_WINE" != "x" ] && [ -x ${WINE_DIR_PREFIX}-${APP_RUN_WINE}/bin/wine ]; then
    WINE_DIR=${WINE_DIR_PREFIX}-${APP_RUN_WINE}
    WINE_CMD=$WINE_DIR/bin/wine
    export WINEDLLPATH=$WINE_DIR/lib:$WINE_DIR/lib64
else
    WINE_CMD="wine"
fi

export WINEPREFIX=$HOME/.local/share/wineprefixes/$APP_NAME

###################################################################################################
# wechat $APP_RUN_WINE=""
if [ -n "$APP_RUN_WINE" ]; then
    if [ -x ${WINE_DIR_PREFIX}-${APP_RUN_WINE}/bin/wine ]; then
        WINE_DIR=${WINE_DIR_PREFIX}-${APP_RUN_WINE}
        WINE_CMD=$WINE_DIR/bin/wine
        export PATH=$WINE_DIR/bin:$PATH
        export WINEDLLPATH=$WINE_DIR/lib:$WINE_DIR/lib64
    else
        zenity --timeout 3 --warning --title="警告！" --text="未安装最佳适配版本 wine-${APP_RUN_WINE}，您可以使用以下命令安装：\n\n\tsudo apt install wine-${APP_RUN_WINE}\n\n\t否则，将使用默认 wine 版本 运行" || :
    fi
fi

# 如果没有安装默认 wine 版本，将使用已存在的最高版本
#if [ ! -x /usr/bin/wine ]; then
if [ ! -x ${WINE_DIR_PREFIX}-${APP_RUN_WINE}/bin/wine ]; then
    WINE_CMD=`ls /opt/wine-*/bin/wine | sort -V | tail -n 1`
    if [ "x$WINE_CMD" != "x" ];then
        WINE_DIR=$(dirname `dirname $WINE_CMD`)
        export PATH=$WINE_DIR/bin:$PATH
        export WINEDLLPATH=$WINE_DIR/lib:$WINE_DIR/lib64
    else
        zenity --error --text="错误！" --text="无法继续运行，请先安装wine软件包。"
        exit 1
    fi
fi

if [ `uname -m` == "loongarch64" ]; then
    mmap_min=`/usr/sbin/sysctl -n vm.mmap_min_addr`
    #mmap_min=`cat /proc/sys/vm/mmap_min_addr`
    if [ $mmap_min -lt 65536 ]; then
        zenity --error --text="错误！" --text="请用管理员用户运行以下命令后再重新运行\n\nsysctl vm.mmap_min_addr=65536"
        exit 1
    fi

#    if ! grep "\[never\]" /sys/kernel/mm/transparent_hugepage/enabled >/dev/null; then
#        zenity --error --text="警告！" --text="请用管理员用户运行以下命令后再重新运行\n\necho never > /sys/kernel/mm/transparent_hugepage/enabled"
#        exit 1
#    fi
fi
###################################################################################################

usage()
{
    cat << ENDLINE
$0 [OPTIONS...]
运行当前容器的默认应用程序-`basename $APP_RUN_CMD`
Option:
  -c --console          运行当前容器的终端窗口
  -f --winefile         运行当前容器的资源管理器
  -s --winecfg          运行当前容器的设置工具
  -r --regedit          运行当前容器的注册表
  -t --taskmgr          运行当前容器的任务管理器
  -u --uninstaller      运行当前容器的添加/删除程序
  -n --notepad          运行当前容器的记事本
  -b --browser          浏览当前容器的文件
  -d --debug <DEBUG>    以Debug方式运行当前容器的默认应用
  -e --reset            重置当前容器到首次启动前状态
  -h --help             显示帮助
ENDLINE
}

app_fix()
{
  local prefix=$1

  # regedit
  for i in system userdef user; do
    sed -i "s#home\\\\\\\\$FAKE_USER#home\\\\\\\\$USER#g" $prefix/$i.reg
    sed -i "s#users\\\\\\\\$FAKE_USER#users\\\\\\\\$USER#g" $prefix/$i.reg
    sed -i "s#home/$FAKE_USER#home/$USER#g" $prefix/$i.reg
    sed -i "s#users/$FAKE_USER#users/$USER#g" $prefix/$i.reg
  done
  sed -i "s#\"USERNAME\"=\"$FAKE_USER\"#\"USERNAME\"=\"$USER\"#" $prefix/user.reg

  # Public User
  if [ ! -d "$prefix/drive_c/users/Public" ]; then
      mkdir -p "$prefix/drive_c/users/Public"
      for i in Desktop Documents Downloads Music Pictures Videos; do
          mkdir -p "$prefix/drive_c/users/Public/$i"
      done
  fi

  # Normal User
  if [ ! -d "$prefix/drive_c/users/$FAKE_USER" ]; then
      mkdir -p "$prefix/drive_c/users/$USER"
  else
      mv "$prefix/drive_c/users/$FAKE_USER" "$prefix/drive_c/users/$USER"
  fi

  mkdir -p "$prefix/drive_c/users/$USER/AppData"
  mkdir -p "$prefix/drive_c/users/$USER/Contacts"
  mkdir -p "$prefix/drive_c/users/$USER/Favorites"
  mkdir -p "$prefix/drive_c/users/$USER/Links"
  mkdir -p "$prefix/drive_c/users/$USER/Saved Games"
  mkdir -p "$prefix/drive_c/users/$USER/Searches"
  mkdir -p "$prefix/drive_c/users/$USER/Temp"

  if [ -f $HOME/.config/user-dirs.dirs ]; then
      source $HOME/.config/user-dirs.dirs
      ln -sf $XDG_DESKTOP_DIR $prefix/drive_c/users/$USER/Desktop
      ln -sf $XDG_DOWNLOAD_DIR $prefix/drive_c/users/$USER/Downloads
      ln -sf $XDG_DOCUMENTS_DIR $prefix/drive_c/users/$USER/Documents
      ln -sf $XDG_MUSIC_DIR $prefix/drive_c/users/$USER/Music
      ln -sf $XDG_PICTURES_DIR $prefix/drive_c/users/$USER/Pictures
      ln -sf $XDG_VIDEOS_DIR $prefix/drive_c/users/$USER/Videos
      ln -sf $XDG_TEMPLATES_DIR $prefix/drive_c/users/$USER/Templates
  else
      if [ -d /home/$USER/桌面 ]; then
          ln -sf /home/$USER/桌面 $prefix/drive_c/users/$USER/Desktop
      elif [ -d /home/$USER/Desktop ]; then
          ln -sf /home/$USER/Desktop $prefix/drive_c/users/$USER/Desktop
      else
          mkdir -p $prefix/drive_c/users/$USER/Desktop
      fi

      if [ -d /home/$USER/文档 ]; then
          ln -sf /home/$USER/文档 $prefix/drive_c/users/$USER/Documents
      elif [ -d /home/$USER/Documents ]; then
          ln -sf /home/$USER/Documents $prefix/drive_c/users/$USER/Documents
      else
          mkdir -p $prefix/drive_c/users/$USER/Documents
      fi

      if [ -d /home/$USER/下载 ]; then
          ln -sf /home/$USER/下载 $prefix/drive_c/users/$USER/Downloads
      elif [ -d /home/$USER/Downloads ]; then
          ln -sf /home/$USER/Downloads $prefix/drive_c/users/$USER/Downloads
      else
          mkdir -p $prefix/drive_c/users/$USER/Downloads
      fi

      if [ -d /home/$USER/音乐 ]; then
          ln -sf /home/$USER/音乐 $prefix/drive_c/users/$USER/Music
      elif [ -d /home/$USER/Music ]; then
          ln -sf /home/$USER/Music $prefix/drive_c/users/$USER/Music
      else
          mkdir -p $prefix/drive_c/users/$USER/Music
      fi

      if [ -d /home/$USER/图片 ]; then
          ln -sf /home/$USER/图片 $prefix/drive_c/users/$USER/Pictures
      elif [ -d /home/$USER/Pictures ]; then
          ln -sf /home/$USER/Pictures $prefix/drive_c/users/$USER/Pictures
      else
          mkdir -p $prefix/drive_c/users/$USER/Pictures
      fi

      if [ -d /home/$USER/视频 ]; then
          ln -sf /home/$USER/视频 $prefix/drive_c/users/$USER/Videos
      elif [ -d /home/$USER/Videos ]; then
          ln -sf /home/$USER/Videos $prefix/drive_c/users/$USER/Videos
      else
          mkdir -p $prefix/drive_c/users/$USER/Videos
      fi

      if [ -d /home/$USER/模板 ]; then
          ln -sf /home/$USER/模板 $prefix/drive_c/users/$USER/Templates
      elif [ -d /home/$USER/Templates ]; then
          ln -sf /home/$USER/Templates $prefix/drive_c/users/$USER/Templates
      elif [ -d /home/$USER/.Templates ]; then
          ln -sf /home/$USER/.Templates $prefix/drive_c/users/$USER/Templates
      fi
  fi

  if [ ! -d $prefix/dosdevices ]; then
      mkdir -p $prefix/dosdevices/
      ln -sf ../drive_c $prefix/dosdevices/c:
      ln -sf / $prefix/dosdevices/z:
      for i in `seq 0 15`; do
          if [ -c /dev/ttyS${i} ]; then
              ln -sf /dev/ttyS${i} $prefix/dosdevices/com$(( $i+1 ))
          fi
      done
  fi
}

call_process()
{
    if [ $OPT_DEBUG != "n" ]; then
        export WINEDEBUG="$OPT_DEBUG"
    fi

    if [ -n "$APP_RUN_PATH" ];then
        cd "$WINEPREFIX/$APP_RUN_PATH"
        exec $WINE_CMD "$APP_RUN_CMD" "$@"
    else
	#echo $APP_RUN_CMD: Please confirm the execution path -- \"APP_RUN_PATH\"
	#exit 1
        cd "$WINEPREFIX"
        exec $WINE_CMD "$APP_RUN_CMD" "$@"
    fi
}

call_wechat()
{
    if [ "$APP_RUN_WINE" = " " ];then
        WINE_CMD=/opt/deepin-wine6-stable/bin/wine
    fi
    call_process "$@"
}

call_vilin()
{
    local args
    args="--url=$@"
    call_process "$args"
}

call_foxmail()
{
    export LATX_SOFTFPU=1
    local args
    args="$@ -in-process-gpu"
    call_process "$args"
}

call_World-of-Warcraft()
{
    local args
    args="cmd.exe /c $@"
    call_process "$args"
}

call_app()
{
    case $APP_NAME in
        "wechat")
            call_wechat "$@"
	    ;;
        "vilin")
            call_vilin "$@"
	    ;;
        "foxmail")
            call_foxmail "$@"
	    ;;
        "World-of-Warcraft")
            call_World-of-Warcraft "$@"
	    ;;
	*)
	    call_process "$@"
	    ;;
    esac
}

app_install()
{
    if [ -d $WINEPREFIX ] && [ -d $WINEPREFIX/drive_c ]; then
        return
    fi

    mkdir -p $WINEPREFIX
    tar xf $APP_DIR/$APP_ARCHIVE -C $WINEPREFIX
    app_fix $WINEPREFIX
    echo "$APP_VERSION" > "$WINEPREFIX/app_version"
}

app_update()
{
    local app_ignore
    if [ -f "$WINEPREFIX/app_version" ] && [ "$(cat "$WINEPREFIX/app_version")" = "$APP_VERSION" ]; then
        return
    fi

    if [ -f $APP_DIR/$APP_IGNORE ]; then
        app_ignore=$APP_DIR/$APP_IGNORE
    else
        app_ignore=`mktemp /tmp/.appignore.XXXX`
        cat > $app_ignore << EOF
user.reg
userdef.reg
system.reg
EOF
    fi

    tar xf $APP_DIR/$APP_ARCHIVE -C $WINEPREFIX --exclude-from=$app_ignore
    #rm -f $app_ignore

    app_fix $WINEPREFIX
    rm $WINEPREFIX/app_version
    echo "$APP_VERSION" > "$WINEPREFIX/app_version"
}

app_run()
{
    local name=$APP_NAME
    if [ "x$APP_NAME_CN" != "x" ];then
        name=$APP_NAME_CN
    fi

    if [ ! -d "$WINEPREFIX" ]; then
        app_install | progressbar $name "首次启动，初始化$name中..."
    else
        app_update | progressbar $name "正在更新$name中..."
    fi

    call_app "$@"
}

progressbar()
{
    WINDOWID="" zenity --progress --title="$1" --text="$2" --pulsate --width=400 --auto-close --no-cancel
}

##################################
##################################
set -o errexit -o pipefail -o noclobber -o nounset

! getopt --test > /dev/null
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
    echo 'I’m sorry, `getopt --test` failed in this environment.'
    exit 1
fi

LONGOPTS=console,debug:,reset,winefile,winecfg,help,regedit,taskmgr,uninstaller,notepad,browser
OPTIONS=cd:efshrtunb

! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
    exit 2
fi
eval set -- "$PARSED"

while true; do
    case "$1" in
        -c|--console)
            APP_RUN_PATH="drive_c/windows"
            APP_RUN_CMD=wineconsole
            shift
            ;;
        -d|--debug)
            OPT_DEBUG="$2"
            shift 2
            ;;
        -e|--reset)
            OPT_RESET=y
            shift
            ;;
        -f|--winefile)
            APP_RUN_PATH="drive_c/windows"
            APP_RUN_CMD=winefile
            shift
            ;;
        -r|--regedit)
            APP_RUN_PATH="drive_c/windows"
            APP_RUN_CMD=regedit
            shift
            ;;
        -s|--winecfg)
            APP_RUN_PATH="drive_c/windows"
            APP_RUN_CMD=winecfg
            shift
            ;;
        -t|--taskmgr)
            APP_RUN_PATH="drive_c/windows"
            APP_RUN_CMD=taskmgr
            shift
            ;;
        -u|--uninstaller)
            APP_RUN_PATH="drive_c/windows"
            APP_RUN_CMD=uninstaller
            shift
            ;;
        -n|--notepad)
            APP_RUN_PATH="drive_c/windows"
            APP_RUN_CMD=notepad
            shift
            ;;
        -b|--browser)
            APP_RUN_PATH=""
            APP_RUN_CMD="file://$WINEPREFIX"
            WINE_CMD=xdg-open
            shift
            ;;
        -h|--help)
            OPT_HELP=y
            shift
            ;;
        --)
            shift
            break
            ;;
        *)
            echo "Programming error"
            exit 3
            ;;
    esac
done

if [ $OPT_HELP == "y" ];then
    usage
    exit 0
fi

if [ $APP_NAME == "wine-run" ]; then
    echo "nothing to do"
    exit 1
fi

if [ "x${OPT_RESET}" == "xy" ]; then
    rm -rf $WINEPREFIX
    exit
fi

if ! command -v zenity >/dev/null 2>&1;then
    echo "please install package zenity"
    exit 1
fi

app_run "$@"
