#!/usr/bin/bash

# tdm: session selector after login.

# This file is part of tdm, a tiny display manager.
#
# tdm is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# tdm is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with tdm.  If not, see <http://www.gnu.org/licenses/>.

VERSION="1.4.1"

xstart=false
xrunning_check=true
silent=false

nulltype(){
    type "$1" > /dev/null 2>/dev/null
}

function load_confdir_path() {
    # usage: load_confdir_path
    for cfd in "${XDG_CONFIG_HOME:-$HOME/.config}/tdm" "$HOME/.tdm" ; do
        if [ -d "$cfd" ] ; then
            echo "$cfd"
            return
        fi
    done
    echo "${XDG_CONFIG_HOME:-$HOME/.config}/tdm"
}


fallback(){
    if [ -n "$1" ]; then
        $silent || echo -e '\033[31;1m'"$1"'\033[0m'
    fi
    exit 1
}

get_needs(){
    local _type
    _type="$(file -p --mime-type "$1" | awk '{print $2}' | cut -d'/' -f1)"
    if [ "${_type}" == "text" ]; then
        grep '#[ \t]*needs[ \t]*:' "$1"|sed -e 's/#.*://g'
    fi
}

valid_item(){
    local needs
    read -r -a needs<<<"$(get_needs "$1")"
    for _i in "${needs[@]}"
    do
        nulltype "${_i}" || return 1
    done
    return 0
}

# directory settings
CONFDIR="$(load_confdir_path)"
SESSIONS=${CONFDIR}/sessions
EXTRA=${CONFDIR}/extra
SAVELAST=1
STARTXARGS=

eval set -- "$(
    getopt -o h \
    --long help \
    --long xstart \
    --long disable-xrunning-check \
    --long silent \
    -n "$(basename "$0")" -- "$@" || \
    echo usage
    )"

if [ "$CONFDIR" == "$HOME/.tdm" ] ; then
    echo "Following tdm v1.3.0, the configuration files should be moved to '${XDG_CONFIG_HOME:-$HOME/.config}/tdm' in order to become XDG compliant"
    echo "Use 'tdmctl migrate' to automatically migrate your configuration to the new location"
    echo "Support for the old configuration directory ($CONFDIR) will be dropped in tdm 2.x.y"
fi

if [ -z "$XDG_VTNR" ]; then
    XDG_VTNR="$(tty | sed -n -e 's|^/dev/tty\([1-9][0-9]*\)|\1|p')"
    export XDG_VTNR
fi

while [ $# -gt 0 ]; do
    case "$1" in
        '--xstart')
            xstart=true
        ;;
        '--disable-xrunning-check')
            xrunning_check=false
        ;;
        '--silent')
            silent=true
        ;;
        '--help'|'-h')
            usage 0
        ;;
        '--')
            shift
            break
        ;;
        *)
            >&2 printf 'Whoops, option "%s" is not yet implemented!\n' "$1"
            exit 42
        ;;
    esac
    shift
done

if [ $# -gt 0 ]; then
  >&2 echo 'Too many arguments.'
  exit 2
fi

# started from startx, so start session
if "$xstart" ; then
    if [[ -f "${CONFDIR}/tdmexit" ]]; then
        # shellcheck source=tdmexit
        . "${CONFDIR}/tdmexit"
    fi
    if [[ -x "/tmp/tdmdefault" ]]; then
        exec /tmp/tdmdefault
    else
        exec "${CONFDIR}/default"
    fi
fi

clear
# check for a 'good' tty
(basename "$(tty)" |grep -q tty) || fallback "Invalid tty"

# X started, exit
$xrunning_check && [[ "$(find /tmp/.X11-unix -type s | wc -l)" -gt 0 ]] && fallback 'X started.'

# build confdir
if [ ! -d "${CONFDIR}" ]; then
    tdmctl init
fi

# otherwise, run as the session chosen script
if [[ -f "${CONFDIR}/tdminit" ]]; then
    # shellcheck source=tdminit
    source "${CONFDIR}/tdminit"
fi

# XID: X session Number
# TOTAL: Number of items
# sid : id that user selects

((XID=0))
((TOTAL=0))
xsessions=()
prglist=()
DEFOPT=()

if [[ -x "${CONFDIR}/default" ]]; then
    SDEFAULT=$(readlink "${CONFDIR}/default")
    DEFAULTWM=$(basename "${SDEFAULT}")
else
    SDEFAULT=
    DEFAULTWM=
fi

if [ -d "${SESSIONS}" ]; then
    for script in "${SESSIONS}"/*; do
        if [ -x "${script}" ] && valid_item "${script}" ; then
            xsessions[$XID]="${script}"
            NAME=$(basename "${script}")
            prglist=("${prglist[@]}" "${XID}" "${NAME}")
            if [[ "${NAME}" == "${DEFAULTWM}" ]]; then
                DEFOPT=("--default-item" "${XID}")
            fi
            (( XID=XID+1 ))
            (( TOTAL=TOTAL+1 ))
        fi
    done
else
    echo "${SESSIONS} doesn't exist."
    echo "Making this directory."
    mkdir -p "${SESSIONS}"
fi

if [ -d "${EXTRA}" ]; then
    for script in "${EXTRA}"/*; do
        if [ -x "${script}" ] && valid_item "${script}" ; then
            xsessions[$TOTAL]="${script}"
            NAME="extra/$(basename "${script}")"
            prglist=("${prglist[@]}" "${TOTAL}" "${NAME}")
            (( TOTAL=TOTAL+1 ))
        fi
    done
fi

if [ $TOTAL -eq 0 ]; then
    fallback "No sessions found."
fi

tdm_curses(){
    tempfile="/tmp/tdm_$$"
    trap 'rm -f ${tempfile}' 0 1 2 3 6 14 15
    dialog "${DEFOPT[@]}" --menu "TDM ${VERSION}" 0 0 0 "${prglist[@]}" 2>${tempfile}
    sid=$(cat ${tempfile})
    [ -n "$sid" ]||fallback "Falling back to shell."
}

tdm_text(){
    echo "This is TDM ${VERSION}, a tiny display manager."
    echo "Please select from the following: (default ${DEFAULTWM})"

    local _i=0
    while [ ${_i} -lt ${TOTAL} ]
    do
        echo "${_i} ${prglist[${_i}*2+1]}"
        (( _i=_i+1 ))
    done

    echo -n "Program ID: "
    read -r sid
}

if ! nulltype dialog; then
#no dialog program, force to use tdm_text
    TDMUI=tdm_text
elif [ ! "${TDMUI}" == "tdm_text" ]; then
    TDMUI=tdm_curses
fi
${TDMUI}

rm -f /tmp/tdmdefault
if [[ (-n $sid) && ($sid -lt $TOTAL) && ($sid -ge $XID) ]]; then
    exec "${xsessions[$sid]}"
elif [[ (-n $sid) && ($sid -lt $XID) && ($sid -ge 0) ]]; then
    if [[ ${SAVELAST} -ne 0 ]]; then
        ln -sf "${xsessions[${sid}]}" "${CONFDIR}/default"
    else
        ln -sf "${xsessions[${sid}]}" "/tmp/tdmdefault"
    fi
    startx ${STARTXARGS}
else
    echo "Unknown value, load default."
    if [ -x "${CONFDIR}/default" ]; then
        startx ${STARTXARGS}
    else
        fallback "Session not defined, fallback."
    fi
fi
