#!/bin/bash

# GETTEXT_KEYWORD="gt"
# GETTEXT_KEYWORD="pfgt"
# GETTEXT_KEYWORD="vexit"
# GETTEXT_KEYWORD="error_box_pf"

antiX_lib=/usr/local/lib/antiX

#source $antiX_lib/antiX-get-param.sh
source $antiX_lib/antiX-common.sh     "$@"
last_ps_file=$LIVE_DIR/config/last-persist-save

TITLE=$"antiX Save Persistent Root"

BLURB="$(pf "\n    %s\n    %s\n"                                                                 \
    "`pf $"Manually save filesystem changes in %s file for persistent root." "[f]rootfs[/]"`"    \
    "`pf $"You MUST run a program like this to save your filesystem changes." "[b]" "[/]"`")"

SAFETY_MARGIN=2

main() {
    read_options "$@"
    extra_args   0

    SYS_TYPE="LiveCD/USB/HD"
    read_conf || read_conf_error "rootfs"

    # error_box                                                                       \
    #     "$(pfgt "This script can only be run in a %s environment" "$SYS_TYPE")"                  \
    #     "$(pfgt "where the device holding the %s file can be written to." "[f]rootfs[/]")"       \
    #     ""                                                                                       \
    #     "$(pfgt "The file %s was not found" "[f]$CONF_DIR/$ME.conf[/]")"                         \
    #     "$(pfgt "This indicates that %s can't be run on this system." "$ME")"                    \
    #     ""                                                                                       \

    show_cli_title

    # First make sure script is run as root.
    need_root
    start_logging
    save_log_file

    grep -q "^PERSISTENCE=.*dynamic" /live/config/initrd.out || error_box_pf "%s was not enabled.  Cannot %s" "Dynamic root persistence" "${0##*/}"

    noisy_yes_no_box                       \
        $"Shall we begin?"                 \
        || vexit "Stopping at user's request"

    trap clean_up EXIT
    create_lock

    check_persist_uuid || error_box "Error when checking for %s device" 'persistence'

    if which alsactl &>/dev/null; then
        vpf "Storing volume settings"
        # *** sigh ***
        HOME=/root alsactl  --ignore store 2>/dev/null
    fi

    mount_if_needed $PERSIST_DEV $PERSIST_MP
    make_readwrite $PERSIST_MP

    mount_if_needed -o loop $PERSIST_FILE $ROOTFS_MP
    make_readwrite $ROOTFS_MP

    check_vid "$ROOTFS_MP" "$SQFS_MP" || vexit "On VID error"

    # Check for available space. If ok continue else stop.
    #FIXME: should offer to make a new rootfs if we don't have enough room.

    bg_info_box -o "$PULSATE"                    \
        "$TITLE"                                 \
        ""                                       \
        $"Checking for existing files and"       \
        $"Checking if there is enough room ..."  \

    local upper
    local root_fs=$(df -T / | tail -n1 | awk '{print $2}')
    [ "$root_fs" = "overlay" ] && upper="/upper"

    excludes="$(rootfs_excludes $AUFS_RAM_MP$upper)"
    exclude_size="$(du_size $excludes)"

    pdev_total=$(all_space  $PERSIST_MP)
    pdev_avail=$(free_space $PERSIST_MP)

    rootfs_file_size=$(du_size $(readlink -f $PERSIST_FILE))

    aufsrw_used=$(du_size $AUFS_RAM_MP)
    rootfs_used=$(du_size $ROOTFS_MP)

    rootfs_full=$(all_space $ROOTFS_MP)

    # Reduce available size by 10% for a safety margin and because
    # the du and df commands give different sizes.
    safe_full=$(( $rootfs_full * 90 / 100 ))
    need_size=$(( $aufsrw_used - $exclude_size ))
    xfer_size=$(( $need_size - $rootfs_used))
    [ "$xfer_size" -lt "10" ] && xfer_size="?"

    main_text=(
        "$(fmt_size "reported rootfs space"  $rootfs_full)"
        "$(fmt_size "total rootfs space"     $safe_full)"
        "$(fmt_size "used rootfs space"      $rootfs_used)"
        "$(fmt_size "excluded file size"     $exclude_size)"
        "$(fmt_size "required rootfs space"  $need_size)"
        "$(fmt_size "approx. transfer size"  $xfer_size)"
        ""
        "$(pf "%12s: %s"  $"persist device" "[f]$PERSIST_DEV[/]")"
        "$(pf "%12s: %s"  $"mounted at"     "[f]$PERSIST_MP[/]")"
        ""
        "$(fmt_size "persist device total" $pdev_total)"
        "$(fmt_size "persist device free"  $pdev_avail)"
    )

    for t in "${main_text[@]}"; do
        vmsg "$t"
    done

    kill_bg_info_box

    [ "$rootfs_full" -lt "$SAFETY_MARGIN" ] && \
        error_box_pf "Available space, %s, is smaller than the margin of %s." \
            "[n]$rootfs_full[/]" "[n]$SAFETY_MARGIN[/]"

    [ "$safe_full" -lt "$need_size" ] && \
        error_box_pf "Insufficient space.  Have: %s. Need: %s." "[n]$safe_full[/]" "[n]$need_size[/]"

    noisy_yes_no_box                                    \
        $"Ready to sync file system changes"     \
        "[fixed]"                                       \
        "${main_text[@]}"                               \
        "[/]"                                           \
        $"Shall we begin?"                       \
        || vexit "Stopping at user's request"

    bg_info_box -o "$PULSATE" "$TITLE" ""            \
    $"Performing rsync ... please be patient" \
        ""
    exclude_file=$CONF_DIR/rsync.exclude

    #lifo_string TO_DELETE $exclude_file

    rootfs_excludes "/${upper#/}" | sort -u > $exclude_file

    rsync_opts="-a --delete-excluded --exclude-from=$exclude_file $AUFS_RAM_MP/ $ROOTFS_MP/"
    vmsg "rsync $rsync_opts"

    restore_live

    #-jbb if [ "$AUFS_MP" ] && which auplink &>/dev/null; then
    #-jbb     local t0=$(get_time)
    #-jbb     qmsg ">> aplink $AUFS_MP flush"
    #-jbb     auplink $AUFS_MP flush
    #-jbb     local elapsed=$(elapsed $t0)
    #-jbb     qmsg "<< took $elapsed"
    #-jbb fi

    #--- now do the rsync
    time_cmd_quiet rsync -a $rsync_opts
    rsync_ret=$?
    # sync now because we are about to umount
    sync

    full_rootfs=$(all_space  $ROOTFS_MP)
    used_rootfs=$(used_space $ROOTFS_MP)
    free_rootfs=$(free_space $ROOTFS_MP)

    clean_up && trap EXIT

    kill_bg_info_box

    [ "$rsync_ret" != "0" ] && error_box                                      \
        "$(pf $"%s The rsync command failed Failed! %s" "[e][b]" "[/][/]")"  \
        ""                                                                    \
        "$(pf $"It returned an exit code of %s" "[n]$rsync_ret[/]")"         \
        $"See the rsync man page to look up its meaning."            \
        ""

    if [ "$SET_QUIET" ]; then
        timeout_box 2 "$(pf $"%s succeeded" $ME)"
        exit 0
    fi

    date +%s > $last_ps_file

    info_box                                              \
        "$(pf $"%s succeeded" $ME)"                       \
        ""                                                \
        $"    Your changes were saved in:"                \
        "    [f]$PERSIST_FILE[/]"                         \
        "[fixed]"                                         \
        "$(fmt_size "total rootfs space" $full_rootfs)"   \
        "$(fmt_size "used rootfs space"  $used_rootfs)"   \
        "$(fmt_size "free rootfs space"  $free_rootfs)"   \
        "[/]"

    exit 0
}

get_vid() { [ -r "$1" ] && grep ^=== $1 | tail -n 1   ;}

check_vid() {
    local base=$1 linuxfs_mp=$2
    test -d $base/upper && base=$base/upper
    local linuxfs_vf=$linuxfs_mp/etc/live/version/linuxfs.ver
    test -e $linuxfs_vf || return 0
    local linuxfs_vid=$(get_vid $linuxfs_vf)
    [ "$linuxfs_vid" ] || return 0

    local rvf=/etc/live/version/rootfs.ver
    local rootfs_vf=$base$rvf
    [ -z "$rootfs_vf" ] && error_box_pf "Missing rootfs version file %s" "[n]$rvf[/]"

    local rootfs_vid=$(get_vid $rootfs_vf)
    [ -z "$rootfs_vid" ] && error_box_pf "Missing version ID in rootfs file system"

    [ "$rootfs_vid" != "$linuxfs_vid" ] \
        && error_box_pf "Version id inside of %s file does not match" "[n]rootfs[/]"

    return 0
}

#------------------------------------------------------------------------------
#
#------------------------------------------------------------------------------
check_persist_uuid() {
    local uuid_dev=$(blkid -U "$PERSIST_UUID" -c /dev/null)
    if [ -n "$uuid_dev" ]; then
        PERSIST_DEV="$uuid_dev"
        return 0
    fi

    if [ "$ENCRYPTED" ]; then
        local crypt_dev=$(blkid -U "$CRYPT_UUID" -c /dev/null)
        [ -z "$crypt_dev" ] && error_box \
            "$(pf $"The encrypted partition with UUID %s was not found" "[n]$CRYPT_UUID[/]")" \
            $"Please plug in the live-usb device and try again"

        local crypt_name=$ME
        if [ -z "$SET_GUI" ]; then
            echo "Encrypted live-usb detected"
            echo "You will be asked to enter the passphrase below"
            cryptsetup open --type luks $crypt_dev $crypt_name || error_box \
                "$(pf $"Failed to open the encrypted partition")"

        else
            local try max_try=3 fail
            for try in $(seq 1 $max_try); do
                get_password "" ""                                         \
                $"Encrypted live-usb detected"                            \
                ""                                                        \
                $"Be sure to set the keyboard layout to English"          \
                ""                                                        \
                "$(pf $"This is try %s out of $s" $try $max_try)"         \
                ""                                                        \
                $"Please enter the passphrase" \
                ""

                fail=

                printf "$UI_RESULT" |  cryptsetup open --type luks $crypt_dev $crypt_name -d - && break

                fail=true

                warn_box $"That passphrase did not match"    \
                         ""                                  \
                         $"Please try again"
            done

            [ "$fail" ] && error_box \
                "$(pf $"Passphrase failed to match after %s attempts" $max_try)"
        fi

        LUKS_CLOSE="$LUKS_CLOSE $crypt_name"
        PERSIST_DEV=/dev/mapper/$crypt_name

        return 0
    fi

    [ -z "$uuid_dev" ] &&  error_box \
        "$(pf $"The persistence device with UUID %s was not found" "[n]$PERSIST_UUID[/]")" \
        "$(pf $"Please plug in the persistence device and try again")"

    vpf "Using device %s with UUID %s" "[n]$uuid_dev[/]" "[n]$PERSIST_UUID[/]"
    PERSIST_DEV=$uuid_dev
}

main "$@"
