#!/bin/sh
#
# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

: ${XSECURELOCK_XSCREENSAVER_PATH:=}

simple_nl() {
  while read -r line; do
    printf "%d\t%s\n" "$i" "$line"
    i=$((i+1))
  done
}

allsavers() {
  if [ -f ~/.xscreensaver ]; then
    i=0
    printf "%b" "$(
      xrdb -n ~/.xscreensaver 2>/dev/null |\
      grep ^programs: |\
      cut -d : -f 2-
    )" |\
      simple_nl |\
      sed -e '
        s/\t[[:space:]]*/\t/;                # Strip whitespace.
        /\t-/d;                              # Remove disabled hacks.
        s/\t[^[:space:]]*:[[:space:]]*/\t/;  # Remove visual name.
        s/\t"[^"]*"[[:space:]]*/\t/;         # Remove hack name.
      '
  else
    ls "$XSECURELOCK_XSCREENSAVER_PATH" |\
      sed -e 's/$/ -root/' |\
      simple_nl
  fi | while read -r number saver flags; do
    [ -x "$XSECURELOCK_XSCREENSAVER_PATH/$saver" ] || continue
    printf '%d\t%s/%s\n' "$number" "$XSECURELOCK_XSCREENSAVER_PATH" "$saver $flags"
  done
}

mode=$(
  xrdb -n ~/.xscreensaver 2>/dev/null |\
    grep ^mode: |\
    cut -f 2
)

selected=
case "$mode" in
  one)
    selected=$(
      xrdb -n ~/.xscreensaver 2>/dev/null |\
        grep ^selected: |\
        cut -f 2
    )
    ;;
  random)  # NOT random-same.
    # Try bash's $RANDOM, but if it's not there, just use the PID.
    selected=${RANDOM:-$$}
    ;;
esac

if [ -z "$selected" ]; then
  # We're using the parent process ID here, which may be a saver_multiplex
  # instance. This ensures that multiple instances of this always spawn the same
  # saver on each screen.
  selected=$PPID
fi

selectsaver() {
  savers=$(allsavers)
  case "$mode" in
    one)
      count=$(printf '%s\n' "$savers" | wc -l)
      printf '%s\n' "$savers" | grep "^$selected$(printf '\t')"
      ;;
    *)
      count=$(printf '%s\n' "$savers" | wc -l)
      printf '%s\n' "$savers" | tail -n +$((selected % count + 1))
      ;;
  esac | head -n 1 | cut -f 2-
}

# We can just run savers in a loop, until one sticks; xsecurelock will kill our
# entire process group anyway when unlocking.
while :; do
  saver=$(selectsaver)
  if [ -n "$saver" ]; then
    $saver
  fi
  sleep 2
  echo >&2 "xsecurelock: Screen saver failed: $saver. Trying another one..."
  selected=$((selected + 1))
  mode=random
done &

exec ./saver_blank
