#!/bin/bash

# Pacdiff for EndeavourOS.

UserWants() {
    case "$user_wants" in
        cli | both) [ "$1" = "cli" ] && return 0 ;;
    esac
    which yad &>/dev/null || return 1
    case "$user_wants" in
        gui | both) [ "$1" = "gui" ] && return 0 ;;
    esac
    return 1
}

SafetyWarning() {
    if [ "$EOS_PACDIFF_WARNING" = "yes" ] ; then
        local txt=""
        txt+="NOTE: <b>$progname</b> is a powerful tool, so use it carefully!\n\n"
        txt+="For example, please do <i>not</i> modify files like:\n"
        txt+="<tt>    /etc/passwd</tt>\n"
        txt+="<tt>    /etc/group</tt>\n"
        txt+="<tt>    /etc/shadow</tt>\n"
        txt+="and related files unless you know <i>exactly</i> what you are doing.\n\n"
        txt+="You can remove this warning popup by changing the value of\n"
        txt+="variable <tt>EOS_PACDIFF_WARNING</tt> in file <tt>/etc/eos-script-lib-yad.conf</tt>.\n"
        txt+="(Note that you may need to merge the changes from\nfile /etc/eos-script-lib-yad.conf.pacnew first!)\n"

        if UserWants cli ; then
            txt2="$(echo "$txt" | sed -e 's|<[/bit]*>||g' -e 's|\\n|\n|g')"
            printf "%s\n\n" "$txt2" >&2
        fi
        if UserWants gui ; then
            eos_yad --form --image=$ICO_WARNING --title="Warning" --text="$txt" --button="yad-ok!!I understand":1
        fi
    fi
}

HasPacdiffs() { test -n "$(echo q | DIFFPROG=diff /usr/bin/pacdiff)" ; }
DoesSudo()    { groups | grep -Pw 'root|wheel' >/dev/null ; }

PacdiffCmd() {
    local differ="$1"

    if HasPacdiffs ; then
        case "$differ" in            # some differs may need options
            vim) differ+=" -d" ;;
        esac
        local -r doas="/usr/bin/sudo"
        local -r compress="/usr/bin/gzip"   # compress with "gzip" or "zstd --rm"
        local cmdfile
        cmdfile=$(mktemp "$HOME/.tmp.$progname.tmpXXX") || DIE "creating a temporary file under $HOME failed"        # don't mount $HOME with noexec!

        cat <<EOF > $cmdfile
#!/bin/bash
echo "==> starting pacdiff with '$differ' diff support..." >&2
EOF
        if [ $backup_all = yes ] ; then
            local -r pacnews=($(DIFFPROG=diff /usr/bin/pacdiff -o))
            local -r time=$(date +%Y%m%d-%H%M%S)

            cat <<EOF >> $cmdfile
echo "  -> creating backups under folder $backupdir" >&2
$doas /usr/bin/mkdir -p $backupdir
$doas /usr/bin/chmod go-rwx $backupdir
EOF
            local bf bu
            for bf in "${pacnews[@]}" ; do
                bf=${bf%.*}                                          # e.g. /etc/akm.conf
                bu=${bf##*/}.$time                                   # e.g. akm.conf.20250215-170300
                echo "$doas /usr/bin/cp $bf $backupdir/$bu" >> $cmdfile
                echo "$doas $compress $backupdir/$bu"       >> $cmdfile
            done
        fi

        echo "DIFFPROG=\"/usr/bin/$differ\" /usr/bin/pacdiff -s 2>/dev/null" >> $cmdfile
        chmod u+x,go-rwx $cmdfile

        if [ $start_new_terminal = yes ] ; then
            RunInTerminal "$cmdfile"
        else
            bash -c "$cmdfile"
        fi
        rm -f $cmdfile
        return $diffs_yes
    else
        local msg="$progname: nothing to do."
        if UserWants cli ; then
            echo "$indent$msg" >&2
        fi
        if UserWants gui ; then
            eos_yad_nothing_todo "<tt>$msg</tt>" 5
        fi

        [ $start_new_terminal = yes ] && return $diffs_no_nt || return $diffs_no
    fi
}

Usage() {
    cat <<EOF >&2
Usage:    $progname [options]
Options:  -h, --help          This help.
          -b, --backup        Save the old files (in view, merge, and overwrite modes) with .bak. Default.
          --no-backup         The opposite of option --backup.
          --nt                Starts a new terminal for the output (used by the Welcome app).
          --quiet             Do not display messages.
          --msg-types=WHAT    Selects how informational messages will be displayed.
                              Supported values for WHAT:
                                 "cli"   Only using terminal CLI.
                                 "gui"   Only using popup windows.
                                 "both"  "cli" + "gui".
                                 ""      Do not display messages (same as --quiet).
                              Default: "both".
EOF
    case "$1" in
        OK)   exit 0 ;;
        FAIL) exit 1 ;;
    esac
}

DIE() {
    local msg="$1"
    local linenr="${BASH_LINENO[0]}"

    case "$linenr" in
        [1-9]*) linenr=" (line $linenr)" ;;
        *)      linenr="" ;;
    esac
    echo -e "\n==> $progname$linenr: error: $msg\n" >&2
    Usage FAIL
}

Main()
{
    local progname=${0##*/}
    # exit codes
    local diffs_yes=0
    local diffs_error=1
    local diffs_no=2
    local diffs_no_nt=3

    local start_new_terminal=no
    local indent=""
    local user_wants=both
    local -r backup_default=yes
    local backup_all=$backup_default
    local -r backupdir="/etc/.EOS_BACKUPDIR"
    local -r extra_conf=/etc/$progname.conf
    local arg

    DoesSudo || DIE "sorry, user needs to have proper rights for 'sudo'"

    # pre-handling of certain options
    for arg in "$@" ; do
        case "$arg" in
            --quiet)       user_wants="" ;;
            --msg-types=*) user_wants="${1#*=}" ;;             # cli gui both ""
        esac
    done

    source /usr/share/endeavouros/scripts/eos-script-lib-yad || return $diffs_error
    export -f eos_yad
    export -f eos_yad_nothing_todo
    AssignIconVariables_in_eos_bash_shared

    case "$user_wants" in
        gui|both) CanRunYad || user_wants=cli ;;
    esac

    # read config file if it exists; command line options will override config file values
    if [ -e $extra_conf ] ; then
        case "$user_wants" in
            cli | both) echo "==> reading $extra_conf" >&2 ;;
        esac
        source $extra_conf
    else
        echo "==> info: file $extra_conf is not available." >&2
    fi

    # handle rest of the options
    while [ "$1" ] ; do
        case "$1" in
            -h | --help)   Usage OK ;;
            -b | --backup) backup_all=yes ;;
            --no-backup)   backup_all=no ;;
            --indent=*)    indent="${1#*=}" ;;
            --nt)          start_new_terminal=yes ;;
            --quiet)       ;; # user_wants="" ;;
            --msg-types=*) ;; # user_wants="${1#*=}" ;;             # cli gui both ""
            -*)            DIE "option '$1' not supported." ;;
        esac
        shift
    done

    SafetyWarning

    # see /etc/eos-script-lib-yad.conf about EOS_WELCOME_PACDIFFERS

    for differ in "${EOS_WELCOME_PACDIFFERS[@]}" ; do
        if [ -x /usr/bin/${differ%% *} ] ; then
            PacdiffCmd "$differ"
            return $?
        fi
    done
}

Main "$@"
