#!/bin/bash

set -xe

function log_info() {
  local msg=$1
  echo "[INFO] $msg"
}

function log_warn() {
  local msg=$1
  echo "[WARN] $msg"
}

function log_fatal() {
  local msg=$1
  echo "[ERROR] $msg"
  exit 1
}

function install_vnc_ubuntu() {
  sudo apt update -y -qq
  sudo DEBIAN_FRONTEND=noninteractive apt install netcat tigervnc-standalone-server tigervnc-common xdotool -y -qq
}

function install_vnc_centos() {
  if grep -E "release 8\." /etc/redhat-release || grep -E "Red Hat" /etc/redhat-release; then
    sudo yum clean metadata
  else
    sudo yum --enablerepo=updates clean metadata
  fi

  yum -y install epel-release

  # in centos6 no netcat, use nc
  sudo yum install nc netcat tigervnc-server xorg-x11-fonts-Type1 xorg-x11-utils xdotool -y
  if grep -E "release 6\." /etc/redhat-release; then
    # http://archives.fedoraproject.org/pub/archive/epel/6/x86_64/epel-release-6-8.noarch.rpm
    sudo rpm -Uvh https://elrepo.org/linux/elrepo/el6/x86_64/RPMS/elrepo-release-6-12.el6.elrepo.noarch.rpm || true
  fi
}

function configure_vnc_ubuntu() {
  source /etc/lsb-release
  if [ x"$DISTRIB_RELEASE" == x"22.04" ]; then
    configure_vnc_ubuntu_2204
  else
    configure_vnc_ubuntu_below_2204
  fi
}

function configure_vnc_ubuntu_2204() {
  if ! lsb_release -r >/dev/null || ! lsb_release -r | grep "22.04" >/dev/null; then
    log_warn "lsb_release -r no match ubuntu 22.04, return"
    return
  fi

  # 1. insert hack code
  # vncserver -nolisten unix -listen tcp -maxclients 256
  tigervnc_config_module="/usr/share/perl5/TigerVNC/Config.pm"
  line_no=$(grep -n "\$arg eq '--'" ${tigervnc_config_module} | head -n 1 | awk -F: '{print $1}' | tr -d '\n')
  local hack_code=$(
    cat <<-\EOF
      if (defined $pendingExtraArg) {
        push @{$pendingExtraArg->{"args"}}, $arg;
        undef $pendingExtraArg;
        next;
      }
EOF
  )
  sudo sed -i "${line_no} i ${hack_code@Q}" ${tigervnc_config_module}
  sudo sed -i -e "s/\$'//" -e "s/}'/}/" ${tigervnc_config_module}

  cat <<\EOF | sudo tee -a /etc/tigervnc/vncserver-config-defaults
$localhost = "no";
$vncUserDir = "$ENV{VNC_HOME}/.vnc";
$geometry = "2560x1440";
EOF
}

# 22.04 之前 ubuntu 版本中 vncserver hack
function configure_vnc_ubuntu_below_2204() {
  VNCSERVER_BIN=$(which vncserver)

  sudo sed -i 's/catfile($ENV{HOME}, ".vnc")/catfile($ENV{VNC_HOME} ? $ENV{VNC_HOME}: $ENV{HOME} , ".vnc")/' ${VNCSERVER_BIN}

  echo '$localhost = "no";' | sudo tee -a /etc/vnc.conf
  sudo sed -i 's/$geometry = "1900x1200";/$geometry = "2560x1440";/' /etc/vnc.conf
}

function configure_vnc_centos() {
  # 修改 centos vnc 默认分辨率 2560 * 1440
  VNCSERVER_BIN=$(which vncserver)
  sudo sed -i 's/$geometry = "1024x768";/$geometry = "2560x1440";/' ${VNCSERVER_BIN}

  # set vnc home
  sudo sed -i 's#$vncUserDir = "$ENV{HOME}/.vnc";#$vncUserDir = $ENV{VNC_HOME} ? "$ENV{VNC_HOME}/.vnc" : "$ENV{HOME}/.vnc";#' ${VNCSERVER_BIN}

  if grep -E "release 6\." /etc/redhat-release >/dev/null; then

    # fix vncserver list exit 1
    sudo sed -i 's/\(^\s\{4\}exit\) 1;/\1;/' ${VNCSERVER_BIN}
  else
    # centos 环境，解决存在 gnome 桌面情况下 autokill vnc session
    sudo sed -i -e 's/"\(if.*gnome-session -o -e.*\)/"#\1/' -e 's/\(".*\)\(vncserver -kill.*\)/\1#\2/' -e 's/"fi\\n");/"#fi\\n");/' ${VNCSERVER_BIN}

    # 解决 vncserver -list 在 centos 下 exit 1 问题
    sudo sed -i 's/^\(    exit\) 1;$/\1;/' ${VNCSERVER_BIN}

    # fix centos polkit agent error #1458
    if [ -e /etc/xdg/autostart/xfce-polkit.desktop ]; then
      sudo mv -fv /etc/xdg/autostart/xfce-polkit.desktop /tmp/
    fi
  fi
}

function xdg_autostart_vnc_nowin() {
  cat >xdg_autostart_vnc_nowin.desktop <<EOF
[Desktop Entry]
Name=fastone-vnc-conf
Version=1.0
Exec=vncconfig -nowin
Type=Application
EOF

  # clipboard copy/paste rely vnconfig settings
  sudo mv -vf xdg_autostart_vnc_nowin.desktop /etc/xdg/autostart/
}

function checking_for_desktop_installed() {
  declare -A vm_bins
  vm_bins["KDE Plasma"]="startplasma-x11"
  vm_bins["Xfce"]="startxfce4 xfce4-session"
  vm_bins["GNOME"]="gnome-session gnome-shell"
  vm_bins["Cinnamon"]="cinnamon-session"
  vm_bins["i3"]="i3"
  vm_bins["dwm"]="dwm"

  local installed_vms=()

  for wm in "${!vm_bins[@]}"; do
      # take value from associative array
      local bins=${vm_bins[$wm]}
      local bin
      for bin in $bins; do
        if [ -n "$(type -p "$bin")" ]; then
          installed_vms+=("$wm")
          break
        fi
      done
  done

  local len_installed_vms=${#installed_vms[@]}
  if [ "$len_installed_vms" -eq 0 ]; then
    log_fatal "No supported window managers installed."
  elif [ "$len_installed_vms" -gt 1 ]; then
    log_warn "Too many window managers installed, please ensure the one of the following window managers can be started by the xinit: ${installed_vms[*]}."
  fi
}

function checking_for_vnc() {
  log_info "testing vnc server..."

  local display_num="4396"

  vncserver -kill :$display_num || true

  local succeed=false
  if ! echo -e "PwPPpK6irNfGZ\nPwPPpK6irNfGZ\nn\n" | sh -c "VNC_HOME=$(mktemp -d); vncserver :$display_num 2>&1"; then
    log_warn "vnc server not working, please check"
  else
    log_info "vnc server testing succeed"
    succeed=true
  fi

  if ! vncserver -list | grep -q $display_num;then
    log_fatal "the vnc session is not exist in the list after testing"
  fi

  log_info "try to kill vnc server..."
  vncserver -kill :$display_num
  log_info "vnc server killed"

  if ! $succeed; then
    log_fatal "vnc server testing failed"
  fi

}

function main() {
  checking_for_desktop_installed

  if [[ -e /etc/apt/sources.list ]]; then
    install_vnc_ubuntu
    configure_vnc_ubuntu
    remove_screensaver_ubuntu
  elif [[ -d /etc/yum.repos.d ]]; then
    install_vnc_centos
    configure_vnc_centos
    remove_screensaver_centos
  else
    log_fatal "not supported distro"
  fi

  xdg_autostart_vnc_nowin
  checking_for_vnc
}

function remove_screensaver_ubuntu() {
  # fastone/cce-project#10086
  for pkg in xscreensaver xfce4-screensaver xfce4-power-manager gnome-screensaver gnome-power-manager cinnamon-screensaver; do
    sudo apt-get remove -y ${pkg} || true
  done
}

function remove_screensaver_centos() {
  sudo yum remove -y xscreensaver xfce4-screensaver xfce4-power-manager gnome-screensaver gnome-power-manager cinnamon-screensaver
}

main
