# adapted from 200_run_layout_code.sh
#
# Run the DASD format code (dasdformat.sh)
# again and again until it succeeds or the user aborts.
#

# Skip DASD formatting when the user has explicitly specified to not format them
# or when the user selected "Confirm what is currently on the DASDs, skip formatting them"
# in 370_confirm_dasd_format_code.sh

is_false "$FORMAT_DASDS" && return 0

function lsdasd_output () {
    lsdasd 1>> >( tee -a "$RUNTIME_LOGFILE" 1>&7 )
}

rear_workflow="rear $WORKFLOW"
original_disk_space_usage_file="$VAR_DIR/layout/config/df.txt"
rear_shell_history="$( echo -e "cd $VAR_DIR/layout/\nvi $DASD_FORMAT_CODE\nless $RUNTIME_LOGFILE" )"
wilful_input=""

unset choices
choices[0]="Rerun DASD format script ($DASD_FORMAT_CODE)"
choices[1]="View '$rear_workflow' log file ($RUNTIME_LOGFILE)"
choices[2]="Edit DASD format script ($DASD_FORMAT_CODE)"
choices[3]="Show what is currently on the disks ('lsdasd' device list)"
choices[4]="View original disk space usage ($original_disk_space_usage_file)"
choices[5]="Use Relax-and-Recover shell and return back to here"
choices[6]="Confirm what is currently on the disks and continue '$rear_workflow'"
choices[7]="Abort '$rear_workflow'"
prompt="DASD format choices"

choice=""
# When USER_INPUT_DASD_FORMAT_CODE_RUN has any 'true' value be liberal in what you accept and
# assume choices[0] 'Rerun DASD format script' was actually meant
# regardless that this likely lets 'rear recover' run an endless loop
# of failed DASD format attempts but ReaR must obey what the user specified
# (perhaps it is intended to let 'rear recover' loop here until an admin intervenes):
is_true "$USER_INPUT_DASD_FORMAT_CODE_RUN" && USER_INPUT_DASD_FORMAT_CODE_RUN="${choices[0]}"

unset confirm_choices
confirm_choices[0]="Confirm recreated DASD format and continue '$rear_workflow'"
confirm_choices[1]="Go back one step to redo DASD format"
confirm_choices[2]="Use Relax-and-Recover shell and return back to here"
confirm_choices[3]="Abort '$rear_workflow'"
confirm_prompt="Confirm the recreated DASD format or go back one step"
confirm_choice=""
# When USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION has any 'true' value be liberal in what you accept and
# assume confirm_choices[0] 'Confirm recreated DASD format and continue' was actually meant:
is_true "$USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION" && USER_INPUT_DASD_FORMAT_MIGRATED_CONFIRMATION="${confirm_choices[0]}"

# Run the DASD format code (dasdformat.sh)
# again and again until it succeeds or the user aborts
# or the user confirms to continue with what is currently on the disks
# (the user may have setup manually what he needs via the Relax-and-Recover shell):
while true ; do
    prompt="The DASD format had failed"
    # After switching to recreating with DASD format script
    # change choices[0] from "Run ..." to "Rerun ...":
    choices[0]="Rerun DASD format script ($DASD_FORMAT_CODE)"
    # Run DASD_FORMAT_CODE in a sub-shell because it sets 'set -e'
    # so that it exits the running shell in case of an error
    # but that exit must not exit this running bash here:
    ( source $DASD_FORMAT_CODE )
    # One must explicitly test whether or not $? is zero in a separated bash command
    # because with bash 3.x and bash 4.x code like
    #   # ( set -e ; cat qqq ; echo "hello" ) && echo ok || echo failed
    #   cat: qqq: No such file or directory
    #   hello
    #   ok
    # does not work as one may expect (cf. what "man bash" describes for 'set -e').
    # There is a subtle behavioural difference between bash 3.x and bash 4.x
    # when a script that has 'set -e' set gets sourced:
    # With bash 3.x the 'set -e' inside the sourced script is effective:
    #   # echo 'set -e ; cat qqq ; echo hello' >script.sh
    #   # ( source script.sh ) && echo ok || echo failed
    #   cat: qqq: No such file or directory
    #   failed
    # With bash 4.x the 'set -e' inside the sourced script gets noneffective:
    #   # echo 'set -e ; cat qqq ; echo hello' >script.sh
    #   # ( source script.sh ) && echo ok || echo failed
    #   cat: qqq: No such file or directory
    #   hello
    #   ok
    # With bash 3.x and bash 4.x testing $? in a separated bash command
    # keeps the 'set -e' inside the sourced script effective:
    #   # echo 'set -e ; cat qqq ; echo hello' >script.sh
    #   # ( source script.sh ) ; (( $? == 0 )) && echo ok || echo failed
    #   cat: qqq: No such file or directory
    #   failed
    # See also https://github.com/rear/rear/pull/1573#issuecomment-344303590
    if (( $? == 0 )) ; then
        prompt="DASD format had been successful"
        # When DASD_FORMAT_CODE succeeded and when not in migration mode
        # break the outer while loop and continue the "rear recover" workflow
        # which means continue with restoring the backup:
        is_true "$MIGRATION_MODE" || break
        # When DASD_FORMAT_CODE succeeded in migration mode
        # let the user explicitly confirm the recreated (and usually migrated) format
        # before continuing the "rear recover" workflow with restoring the backup.
        # Show the recreated DASD format to the user on his terminal (and also in the log file):
        LogPrint "Recreated DASD format:"
        lsdasd_output
        # Run an inner while loop with a user dialog so that the user can inspect the recreated DASD format
        # and perhaps even manually fix the recreated DASD format if it is not what the user wants
        # (e.g. by using the Relax-and-Recover shell and returning back to this user dialog):
        while true ; do
            confirm_choice="$( UserInput -I DASD_FORMAT_MIGRATED_CONFIRMATION -p "$confirm_prompt" -D "${confirm_choices[0]}" "${confirm_choices[@]}" )" && wilful_input="yes" || wilful_input="no"
            case "$confirm_choice" in
                (${confirm_choices[0]})
                    # Confirm recreated DASD format and continue:
                    is_true "$wilful_input" && LogPrint "User confirmed recreated DASD format" || LogPrint "Continuing with recreated DASD format by default"
                    # Break the outer while loop and continue with restoring the backup:
                    break 2
                    ;;
                (${confirm_choices[1]})
                    # Go back one step to redo DASD format:
                    # Only break the inner while loop (i.e. this user dialog loop)
                    # and  continue with the next user dialog below:
                    break
                    ;;
                (${confirm_choices[2]})
                    # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
                    rear_shell "" "$rear_shell_history"
                    ;;
                (${confirm_choices[3]})
                    abort_dasd_format
                    Error "User did not confirm the recreated DASD format but aborted '$rear_workflow' in ${BASH_SOURCE[0]}"
                    ;;
            esac
        done
    fi
    # Run an inner while loop with a user dialog so that the user can fix things
    # when DASD_FORMAT_CODE failed.
    # Such a fix does not necessarily mean the user must change
    # the dasdformat.sh script when DASD_FORMAT_CODE failed.
    # The user might also fix things by only using the Relax-and-Recover shell and
    # then confirm what is on the disks and continue with restoring the backup
    # or abort this "rear recover" run to re-try from scratch.
    while true ; do
        choice="$( UserInput -I DASD_FORMAT_CODE_RUN -p "$prompt" -D "${choices[0]}" "${choices[@]}" )" && wilful_input="yes" || wilful_input="no"
        case "$choice" in
            (${choices[0]})
                # Rerun or run (after switching to recreating with DASD format script) DASD format script:
                is_true "$wilful_input" && LogPrint "User runs DASD format script" || LogPrint "Running DASD format script by default"
                # Only break the inner while loop (i.e. the user dialog loop):
                break
                ;;
            (${choices[1]})
                # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
                less $RUNTIME_LOGFILE 0<&6 1>&7 2>&8
                ;;
            (${choices[2]})
                # Run 'vi' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
                vi $DASD_FORMAT_CODE 0<&6 1>&7 2>&8
                ;;
            (${choices[3]})
                LogPrint "This is the current list of DASDs:"
                lsdasd_output
                ;;
            (${choices[4]})
                # Run 'less' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
                less $original_disk_space_usage_file 0<&6 1>&7 2>&8
                ;;
            (${choices[5]})
                # rear_shell runs 'bash' with the original STDIN STDOUT and STDERR when 'rear' was launched by the user:
                rear_shell "" "$rear_shell_history"
                ;;
            (${choices[6]})
                # Confirm what is on the disks and continue:
                # Break the outer while loop and continue with restoring the backup:
                break 2
                ;;
            (${choices[7]})
                abort_dasd_format
                Error "User chose to abort '$rear_workflow' in ${BASH_SOURCE[0]}"
                ;;
        esac
    done
# End of the outer while loop:
done

# Local functions must be 'unset' because bash does not support 'local function ...'
# cf. https://unix.stackexchange.com/questions/104755/how-can-i-create-a-local-function-in-my-bashrc
unset -f lsdasd_output
