#!/bin/bash
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
source "$(dirname "$0")/lib/ulib/ulib" || exit 1
urequire DEFAULTS

function display_help() {
    uecho "$scriptname: démonter un système de fichier récursivement

USAGE
    $scriptname mountpoint

OPTION
    -c, --continuous
        Continuer même en cas d'erreur
    -r, --recursive
    -1, --no-recursive
        Spécifier le type de démontage:
        Avec -1, un démontage simple est effectué, comme avec umount. Ce type de
        démontage est automatiquement sélectionné pour les systèmes de fichier
        montés sous le répertoire /media
        Avec -r, le démontage est récursif: tous les systèmes de fichiers qui
        sont montés en-dessous de mountpoint sont démontés puis mountpoint est
        démonté. Tous les systèmes de fichiers bind-montés à partir d'un sous-
        répertoire de mountpoint sont démontés aussi.
    -o, --poweroff
    -k, --no-poweroff
        Après avoir démonté le système de fichier mountpoint, éteindre le
        périphérique qui y correspond. --poweroff est automatiquement activé
        pour les systèmes de fichier montés sous le répertoire /media"
}

continuous=
recursive=auto
poweroff=auto
args=(
    --help '$exit_with display_help'
    -c,--continuous continuous=1
    -r,--recursive recursive=1
    -1,--no-recursive recursive=
    -o,--poweroff poweroff=1
    -k,--no-poweroff poweroff=
)
parse_args "$@"; set -- "${args[@]}"

mountp="$1"
[ -n "$mountp" ] || die "Vous dévez spécifier le système de fichier à démonter"
[ -d "$mountp" ] || die "$mountp: répertoire introuvable"
setx mountp=abspath "$mountp"

args=(
    $(get_verbosity_option) $(get_interaction_option)
    ${continuous:+-c}
)
if [ "$recursive" == 1 ]; then array_add args --recursive
elif [ -z "$recursive" ]; then array_add args --no-recursive
fi
if [ "$poweroff" == 1 ]; then array_add args --poweroff
elif [ -z "$poweroff" ]; then array_add args --no-poweroff
fi
run_as_root "${args[@]}" "$mountp"

if withinpath /media "$mountp"; then
    [ "$recursive" == auto ] && recursive=
    [ "$poweroff" == auto ] && poweroff=1
else
    [ "$recursive" == auto ] && recursive=1
    [ "$poweroff" == auto ] && poweroff=
fi

etitle "Calcul des informations"

setx -a mountps=findmnt -nlo TARGET
array_contains mountps "$mountp" || die "$mountp: répertoire de montage invalide"

function show_all() {
    findmnt -T "$mountp" -Rnlo TARGET
    findmnt -nlo TARGET | awkrun mountp="$mountp" '{ if (substr($0, 1, length(mountp) + 1) == (mountp "/")) print }'
}
if [ -n "$recursive" ]; then
    estepi "Type de démontage: récursif"

    setx -a mounts=evalp show_all // sort -u // \
         awk '{print length($0) "," $0}' // \
         sort -nr // \
         awk '{sub(/[0-9]+,/, ""); print}'

    estepi "${#mounts[*]} systèmes de fichier à démonter"
    if show_debug; then
        edebug "Les systèmes de fichiers suivants seront démontés:"
        for mount in "${mounts[@]}"; do
            estep "$mount"
        done
    fi
else
    estepi "Type de démontage: simple"
fi

setx device=findmnt -T "$mountp" -vnlo SOURCE
[ -n "$device" ] || die "Impossible de trouver le périphérique correspondant à $mountp"
if [ -n "$poweroff" ]; then
    estepi "Le périphérique $device sera éteint après démontage"
else
    edebug "Le périphérique correspondant est $device"
fi

eend

ask_yesno -i "Voulez-vous continuer?" O || die

function die_maybe() {
    [ -n "$continuous" ] && return
    die "$@"
}
etitled "Démontage des systèmes de fichier"
if [ -n "$recursive" ]; then
    for mount in "${mounts[@]}"; do
        estep "$mount"
        umount "$mount" || die_maybe
    done
else
    estep "$mountp"
    umount "$mountp" || die_maybe
fi
eend

if [ -n "$poweroff" ]; then
    etitle "Arrêt des périphériques"
    estep "$device"
    udisksctl power-off -b "$device" || die
    eend

    enote "Vous pouvez maintenant débrancher le périphérique!"
fi

exit 0