#!/bin/bash
#-----------------------------------------------------------------------------
# x11tera_on_lock
# The script to use with the x11tera 'on_connect' function.
# This script is called when a connection occurs.
#-----------------------------------------------------------------------------

# used for remove non primary monitors from active (possible for usage) list
export WITH_MONITORS_OFF=1
# used for remove primary monitor from active (possible for usage) list
# warning: disable it only for debug
# warning: in production primary monitor should be locked
export WITH_PRIMARY_MONITOR_OFF=1
# used for power off connected displays
export WITH_DPMS_OFF=1
# used for unlock session automatically (possible values: lock, unlock, keep)
export WITH_LOGINCTRL=lock
# used for lock attached keyboards
export WITH_LOCK_KEYBOARDS=1
# used for lock attached pointers (mouses, touchpads, trackpoints)
export WITH_LOCK_POINTERS=1

# Don't edit behind this line
operation=$1
case "$operation" in
  all|"")
    echo "x11tera_on_lock ALL operation in progress..."
    operation=all
    ;;
  inout|stage0)
    echo "x11tera_on_lock IN/OUT locking operation in progress..."
    operation=inout
    ;;
  logout|stage1)
    echo "x11tera_on_lock LOGOUT operation in progress..."
    operation=logout
    ;;
  save-config)
    echo "x11tera_on_lock SAVE-CONFIG operation in progress..."
    operation=save-config
    ;;
  clear-config)
    echo "x11tera_on_lock CLEAR-CONFIG operation in progress..."
    operation=clear-config
    ;;
  *)
    echo "unsupported '$operation' operation" 1>&2
    exit 1
    ;;
esac

echo "x11tera_on_lock (uid=$UID, user=$USER, display=$DISPLAY, xauth=$XAUTHORITY, operation=$operation)"

# used for restore monitor settings (permanent configs of this computer)
export TMP_USER_LOCK=/tmp/x11tera_xrandr_lock
export TMP_USER_UNLOCK=/tmp/x11tera_xrandr_restore
export DIR_PERMANENT_CFGS=/etc/termidesk/tera
export PATH_USER_LOCK=$DIR_PERMANENT_CFGS/x11tera_user_lock.conf
export PATH_USER_UNLOCK=$DIR_PERMANENT_CFGS/x11tera_user_unlock.conf
export PATH_GREETER_LOCK=$DIR_PERMANENT_CFGS/x11tera_greeter_lock.conf
export PATH_GREETER_UNLOCK=$DIR_PERMANENT_CFGS/x11tera_greeter_unlock.conf

clear_configs()
{
  for opt in $@; do
    [ ! -z "$opt" ] && rm -fv $opt
  done
  return 0
}

save_configs()
{
  config_mode=$1
  config_user_unlock=$2
  config_user_lock=$3
  config_greeter_unlock=$4
  config_greeter_lock=$5
  # preparation of xrandr restore of monitor modes on client' disconnect
  if [[ ! -z "$(which xrandr)" ]] && [[ "$WITH_MONITORS_OFF" == "1" || "$WITH_MONITORS_OFF" == "yes" ]]; then
    primary_output=""
    primary_mode=""
    large_square=0
    large_output=""
    large_mode=""
    # example: HDMI-0 connected primary 1280x1024+0+1136 inverted (normal left inverted right x axis y axis) 376mm x 301mm
    lines=$(xrandr | grep -v "^[ ]" | grep -E " connected .*x.* \(")
    # search for primary monitor
    while read -r line; do
      x=$(echo "$line" | cut -d'(' -f1)
      x3=$(echo "$x" | cut -d' ' -f3)
      if [ "$x3" = "primary" ]; then
        m=$(echo "$x" | cut -d' ' -f4)
        primary_output=$(echo "$x" | cut -d' ' -f1)
        primary_mode=$(echo "$m" | cut -d'+' -f1)
        break
      else
        mode=$(echo "$x3" | cut -d'+' -f1)
        w=$(echo "$mode" | cut -d'x' -f1)
        h=$(echo "$mode" | cut -d'x' -f2)
        if [ ! -z "$w" -a ! -z "$h" ]; then
          square=$(($w * $h))
          if [ ! -z "$square" ]; then
            if [ $square -gt $large_square ]; then
              large_output=$(echo "$x" | cut -d' ' -f1)
              large_mode=$mode
              large_square=$square
            fi
          fi
        fi
      fi
    done <<< "$lines"
    if [ ! -z "$primary_output" ]; then
      echo "Found primary monitor: $primary_mode at $primary_output"
    else
      echo "WARNING: primary monitor not found" 1>&2
      if [ ! -z "$large_output" ]; then
        echo "WARNING: largest monitor $large_mode will be used as primary at $large_output" 1>&2
        primary_output=$large_output
        primary_mode=$large_mode
      fi
    fi
    # search for other monitors
    u_unlock_modes=""
    u_lock_modes=""
    g_unlock_modes=""
    while read -r line; do
      echo "Found monitor: $line"
      x=$(echo "$line" | cut -d'(' -f1)
      output=$(echo "$x" | cut -d' ' -f1)
      x3=$(echo "$x" | cut -d' ' -f3)
      if [[ ! -z "$x3" ]]; then
        if [[ "$x3" == "primary" ]]; then
          primary="--primary"
          m=$(echo "$x" | cut -d' ' -f4)
          r=$(echo "$x" | cut -d' ' -f5)
        else
          primary=""
          m=$x3
          r=$(echo "$x" | cut -d' ' -f4)
        fi
        mode=$(echo "$m" | cut -d'+' -f1)
        pos_x=$(echo "$m" | cut -d'+' -f2)
        pos_y=$(echo "$m" | cut -d'+' -f3)
        [ -z "$r" ] && rotate="" || rotate=" --rotate $r"
        [ -z "$primary" -a "$output" = "$primary_output" ] && primary="--primary"
        # combine results
        u_unlock_modes="${u_unlock_modes} --output $output --mode $mode $primary --pos ${pos_x}x${pos_y} $rotate"
        if [ ! -z "$primary" ]; then
          u_lock_modes="${u_lock_modes} --output $output --mode $mode $primary --pos 0x0 $rotate"
          g_lock_modes="${g_lock_modes} --output $output --mode $mode $primary --pos 0x0 $rotate"
          g_unlock_modes="${g_unlock_modes} --output $output --mode $mode $primary --pos 0x0 $rotate"
        else
          u_lock_modes="${u_lock_modes} --output $output --off"
          g_lock_modes="${g_lock_modes} --output $output --off"
          #g_unlock_modes="${g_unlock_modes} --output $output --same-as $primary_output --scale-from $primary_mode"
          #g_unlock_modes="${g_unlock_modes} --output $output --auto --same-as $primary_output"
          g_unlock_modes="${g_unlock_modes} --output $output --off"
        fi
      fi
    done <<< "$lines"
    if [ ! -z "$u_unlock_modes" ]; then
      echo $u_unlock_modes > $config_user_unlock
      chmod $config_mode $config_user_unlock
      echo "Unlock user's config saved into '$config_user_unlock'"
    fi
    if [ ! -z "$u_lock_modes" -a ! -z "$config_user_lock" ]; then
      echo $u_lock_modes > $config_user_lock
      chmod $config_mode $config_user_lock
      echo "Lock user's config saved into '$config_user_lock'"
    fi
    if [ ! -z "$g_unlock_modes" -a ! -z "$config_greeter_unlock" ]; then
      echo $g_unlock_modes > $config_greeter_unlock
      chmod $config_mode $config_greeter_unlock
      echo "Unlock greeter's config saved into '$config_greeter_unlock'"
    fi
    if [ ! -z "$g_lock_modes" -a ! -z "$config_greeter_lock" ]; then
      echo $g_lock_modes > $config_greeter_lock
      chmod $config_mode $config_greeter_lock
      echo "Lock greeter's config saved into '$config_greeter_lock'"
    fi
  fi
  return 0
}

is_greeter_active()
{
  for id in $(loginctl show-seat seat0 | grep Sessions= | cut -d'=' -f2); do
    s=$(loginctl show-session $id --p Id --p Remote --p Name --p Type --p Class --p Active --p IdleHint --p LockedHint | tr '\n' ' ' | grep Remote=no.*Class=greeter.*Active=yes)
    if [[ ! -z "$s" ]]; then
      return 0
      break
    fi
  done
  return 1
}

monitors_lock()
{
  lock_mode=""
  list=""
  while read -r line; do
    if [[ ! -z "$(echo \"$line\" | grep primary)" ]]; then
      if [[ "$WITH_PRIMARY_MONITOR_OFF" != "1" && "$WITH_PRIMARY_MONITOR_OFF" != "yes" ]]; then
        continue
      fi
    fi
    output=$(echo "$line" | cut -d' ' -f1)
    lock_mode="$lock_mode --output $output --brightness 0"
    list="$list $output"
  done < <(xrandr | grep -E " connected .*x.* \(")
  if [ ! -z "$lock_mode" ]; then
    xrandr $lock_mode && rc=$? || rc=$?
    if [ $rc -eq 0 ]; then
      echo "Monitor(s)$list locked, code=$rc"
    else
      echo "WARNING: Monitor(s)$list not locked, code=$rc" 1>&2
    fi
  else
    echo "WARNING: There are no monitors to lock" 1>&2
  fi
  return 0
}

monitors_offline()
{
  offline_mode="$1"
  if [[ ! -z "$offline_mode" ]]; then
    xrandr --verbose $offline_mode && rc=$? || rc=$?
    if [ $rc -eq 0 ]; then
      echo "Monitor settings applied, code=$rc"
      return 0
    else
      echo "WARNING: Monitor settings not applied, code=$rc" 1>&2
      return 1
    fi
  else
    echo "WARNING: illegal lock mode to apply" 1>&2
    return 1
  fi
}

if [ "$operation" == "all" -o "$operation" == "inout" ]; then
  # cancellation of xrandr restore of monitor modes on client' disconnect
  clear_configs $TMP_USER_UNLOCK $TMP_USER_LOCK "" ""
  # preparation of xrandr restore of monitor modes on client' disconnect
  if [[ ! -z "$(which xrandr)" ]] && [[ "$WITH_MONITORS_OFF" == "1" || "$WITH_MONITORS_OFF" == "yes" ]]; then
    xrandr | grep " connected" | while read -r line; do
     echo "Found monitor: $line"
    done
    monitors_lock
    applied=0
      if is_greeter_active; then
        permanent_config=$PATH_GREETER_LOCK
      else
        permanent_config=$PATH_USER_LOCK
      fi
    if [ -f $permanent_config ]; then
      offline_mode=$(cat $permanent_config)
      echo "Permanent lock mode ($permanent_config): $offline_mode"
      monitors_offline "$offline_mode" && rc=$? || rc=$?
      if [ $rc -eq 0 ]; then
        applied=1
      fi
    fi
    if [ $applied -eq 0 ]; then
      if grep -E -q "^TERA_VDAGENT_EXTRA_ARGS=\".*--render-mode=near.*\"" /etc/default/tera-vdagent 2>/dev/null; then
        save_configs 666 $TMP_USER_UNLOCK $TMP_USER_LOCK "" ""
        echo "Dynamic restore prepared: $(cat $TMP_USER_UNLOCK)"
        offline_mode=$(cat $TMP_USER_LOCK)
        echo "Dynamic offline mode: $offline_mode"
        monitors_offline "$offline_mode" && rc=$? || rc=$?
        rm -fv $TMP_USER_LOCK
      else
        # Если попали в эту точку, значит tera-vdagent не настроен для работы без
        # создания новых "временных" modes, а это значит, что любой текущий mode
        # может оказаться "временным" и возврат к нему будет невозможен, либо будут
        # происходить чудеса в управлени мониторами (на самом деле чудеса возможны,
        # если хотя-бы раз viewer подключался к серверу и масштабировал экран без
        # near-режима, после чего бы настройка была бы прописана в файле)
        echo "WARNING: render-mode=near not configured" 1>&2
      fi
    fi
  fi

  # power off connected displays
  if [[ ! -z "$(which xset)" ]] && [[ "$WITH_DPMS_OFF" == "1" || "$WITH_DPMS_OFF" == "yes" ]]; then
    echo "Force DPMS mode OFF"
    xset dpms force off
  fi

  # lock attached keyboards
  if [[ ! -z "$(which xinput)" ]] && [[ "$WITH_LOCK_KEYBOARDS" == "1" || "$WITH_LOCK_KEYBOARDS" == "yes" ]]; then
    xinput list | tr '\t' ' ' | grep "\[slave \+keyboard" | grep -v "Virtual core XTEST keyboard" | while read -r line; do
      id=$(echo "$line" | awk -F "id=" '{print $2}' | cut -d' ' -f1)
      if [[ ! -z "$id" ]]; then
        nm=$(echo "$line" | awk -F "id=" '{print $1}')  # | awk -F "↳" '{print $2}'
        echo "Disable keyboard id=$id $nm"
        xinput disable $id
      fi
    done
  fi

  # lock attached pointers (mouses, touchpads, trackpoints)
  if [[ ! -z "$(which xinput)" ]] && [[ "$WITH_LOCK_POINTERS" == "1" || "$WITH_LOCK_POINTERS" == "yes" ]]; then
    xinput list | tr '\t' ' ' | grep "\[slave \+pointer" | grep -v "Virtual core XTEST pointer" | while read -r line; do
      id=$(echo "$line" | awk -F "id=" '{print $2}' | cut -d' ' -f1)
      if [[ ! -z "$id" ]]; then
        nm=$(echo "$line" | awk -F "id=" '{print $1}')  # | awk -F "↳" '{print $2}'
        echo "Disable pointer id=$id $nm"
        xinput disable $id
      fi
    done
  fi
fi

if [ "$operation" == "all" -o "$operation" == "logout" ]; then
  # lock OR unlock session automatically
  if [[ $(which loginctl) ]]; then
    if [[ "$WITH_LOGINCTRL" == "unlock" ]]; then
      for id in $(loginctl show-seat seat0 | grep Sessions= | cut -d'=' -f2); do
        s=$(loginctl show-session $id --p Id --p Remote --p Name --p Type --p Class --p Active --p IdleHint --p LockedHint | tr '\n' ' ' | grep -E "Remote=no.*Class=user.*(Active=no|LockedHint=yes)")
        if [[ ! -z "$s" ]]; then
          echo "Unlock session $s"
          loginctl unlock-session $id
          if [[ $(which dm-tool) ]] && [[ $(grep lightdm$ /etc/X11/default-display-manager) ]]; then
            user="$(loginctl show-session $id --p Name | cut -d'=' -f2)"
            XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 dm-tool switch-to-user "$user"
          fi
          break
        fi
      done
    elif [[ "$WITH_LOGINCTRL" == "lock" ]]; then
      for id in $(loginctl show-seat seat0 | grep Sessions= | cut -d'=' -f2); do
        s=$(loginctl show-session $id --p Id --p Remote --p Name --p Type --p Class --p Active --p IdleHint --p LockedHint | tr '\n' ' ' | grep Remote=no.*Class=user.*Active=yes)
        if [[ ! -z "$s" ]]; then
          echo "Lock session $s"
          loginctl lock-session $id
          if [[ $(which dm-tool) ]] && [[ $(grep lightdm$ /etc/X11/default-display-manager) ]]; then
            XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 dm-tool lock
          fi
          break
        fi
      done
    fi
  fi
fi

if [ "$operation" == "save-config" ]; then
  mkdir -pv $DIR_PERMANENT_CFGS
  clear_configs $PATH_USER_UNLOCK $PATH_USER_LOCK $PATH_GREETER_UNLOCK $PATH_GREETER_LOCK
  save_configs 644 $PATH_USER_UNLOCK $PATH_USER_LOCK $PATH_GREETER_UNLOCK $PATH_GREETER_LOCK
fi

if [ "$operation" == "clear-config" ]; then
  clear_configs $PATH_USER_UNLOCK $PATH_USER_LOCK $PATH_GREETER_UNLOCK $PATH_GREETER_LOCK
fi

exit 0
