#!/bin/bash
#
# Simple service manager for pacman cache cleaner.
#
# Requires packages:
#   pacman-contrib   (for paccache)
#   yad              (for yad)
#   polkit           (for pkexec)
#

source /usr/share/endeavouros/scripts/eos-script-lib-yad || exit 1
export -f eos_yad
AssignIconVariables_in_eos_bash_shared

PaccacheOptions_for_keep() {
    local opts=""
    local lopts="dryrun,move:,remove,arch:,cachedir:,force,help,ignore:,keep:,min-atime:,min-mtime:,nocolor,null,quiet,uninstalled,verbose,version"
    local sopts="dm:ra:c:i:fhk:zquvV"

    opts="$(/usr/bin/getopt -o="$sopts" --longoptions "$lopts" --name "$progname" -- "$@")" || {
        $OptFunc -h
        return 1
    }
    eval set -- "$opts"

    while true ; do
        case "$1" in
            --) shift; break ;;

            # these options we simply ignore or don't want:
            -d|--dryrun|-m|--move) DIE "$FUNCNAME: paccache option $1 was not expected" ;;
            -a|--arch|-c|--cachedir|-i|--ignore|--min-atime|--min-mtime) shift ;;
            -f|--force|-h|--help|--nocolor|-z|--null|-q|--quiet|-u|--uninstalled|-v|--verbose|-V|--version) ;;

            # this is what we are looking for:
            -r|--remove) current_keepcount=3 ;;
            -k|--keep)   current_keepcount="$2"
                         [ "${current_keepcount//[0-9]/}" ] && DIE "cannot parse paccache options.\nFile:\n  $s\nLine:\n  $exec_start_line"
                         shift
                         ;;
        esac
        shift
    done
}

DIE() {
    local msg="$1"
    shift
    if false ; then
        echo "Error: $msg" | eos_yad --text-info --image=$ICO_ERROR --title="$progname error" \
                                     --wrap --width=500 --height=300 --button=yad-quit:1 "$@"
    else
        eos_yad --form --image=$ICO_ERROR --title="$progname error" --text="Error: $msg" --button=yad-quit:1 --scroll "$@"
    fi
    exit 1
}

GetCurrentValues() {
    local t="$timer"
    local s="$service"

    if [ ! -r $s ] ; then
        # service is only under /usr/lib/... so get current values from there
        t="$dir2/$pt"
        s="$dir2/paccache.service"

        local why="Is pacman-contrib installed?"
        test -r $t || DIE "sorry, $t does not exist. $why"
        test -r $s || DIE "sorry, $s does not exist. $why"
    fi

    current_period="$(grep "^OnCalendar=" $t | cut -d '=' -f 2)"
    local -r exec_start_line="$(grep "^ExecStart=" $s | tail -n1)"
    current_keepcount="$(echo "$exec_start_line" | sed -E 's|^ExecStart=[^ \t]+[ \t]*||')"   # try to get all paccache parameters from the ExecStart line
    current_delete_uninstalled=FALSE

    # current_keepcount=$(eval echo ${current_keepcount})
    # PaccacheOptions_for_keep $current_keepcount

    local arg args=()
    for arg in $current_keepcount ; do
        case "$arg" in
            '$PACCACHE_ARGS') args+=($PACCACHE_ARGS) ;;
            *) args+=("$arg") ;;
        esac
    done
    PaccacheOptions_for_keep "${args[@]}"
}

Usage() {
    cat <<EOF
Usage: $progname [options]

Options:
    --defaults         Enable manager with default values (run $period, keep latest $keepcount).
    -v, --verbose      Increase verbosity (= see more terminal output).
    -h, --help         This help.
EOF
    [ -n "$1" ] && exit "$1"
}

AddCommand() {
    local show=yes
    case "$1" in
        --silent) show=no; shift ;;
    esac
    local command="$1"

    cmds+=" ; $command"
    if [ "$verbose" = "yes" ] && [ "$show" = "yes" ] ; then
        echo "$command" >> $vfile
    fi
}

_paccache_cleaner_manager()
{
    local progname=paccache-service-manager
    eos_assert_deps $progname yad || return 1
    local dir=/etc/systemd/system
    local dir2=/usr/lib/systemd/system         # current values may be only here...
    local service=$dir/paccache.service
    local timer=$dir/paccache.timer
    local current_period
    local current_keepcount
    local current_delete_uninstalled
    local pt="paccache.timer"
    local cmd_yad
    local cmds=":" cmds2=() cmd_period cmd_ruk=""
    local xx
    local period_vals=""
    local txt
    local image=$ICO_DISK    # drive-harddisk    # disk-utility
    local result=""
    local field_nr=1
    local indent="<tt>  </tt>"
    local du="$(LANG=C /usr/bin/du --si -s /var/cache/pacman/pkg/ | /usr/bin/awk '{print $1}' | sed 's|\([KMGT]\)$| \1B|')"
    local df="$(LANG=C /usr/bin/df --si | /usr/bin/grep -w /     | /usr/bin/awk '{print $4}' | sed 's|\([KMGT]\)$| \1B|')"
    local options=""
    local defaults=no
    local period=weekly keepcount=2 delete_uninstalled=FALSE
    local first_time=no
    local verbose=no
    local vfile=""     # temporary file for showing all commands in verbose mode
    local keepcount_max=100

    if [ ! -r $service ] ; then
        first_time=yes
    fi

    case "$1" in
        -v | --verbose) options+=" -v"
                        options="${options# }"   # drop leading space
                        verbose=yes
                        vfile="$(mktemp)"
                        ;;
        -h | --help)    Usage 0
                        ;;
        --defaults)     defaults=yes
                        ;;
    esac

    GetCurrentValues

    if [ "$defaults" = "no" ] ; then
        txt="<b>Modifies the service that cleans up pacman cache periodically.\n"
        txt+="Below you'll see settings and their current values.\n\n"
        txt+="Current status:\n"
        txt+="${indent}Package cache usage: $du\n"
        txt+="${indent}Free space on disk: $df</b>\n"
        txt+="\n"

        # List possible period values, and set the default
        for xx in daily weekly monthly ; do
            test -n "$period_vals" && period_vals+="!"           # separator
            test "$xx" = "$current_period" && period_vals+="^"   # default
            period_vals+="$xx"
        done

        cmd_yad=(
            eos_yad --form --width=500 --image=$image
            --title='Pacman cache cleaner service manager' 
            --text="$txt" 
            --field='Cleaning period!How often the package cache will be cleaned':CB                                   "$period_vals" 
            --field='Number of the latest package versions to keep!Keep only the selected number of each package':NUM  "$current_keepcount"
            --field='Remove uninstalled but still cached packages now!One time operation':CHK                          "$current_delete_uninstalled"
        )

        result="$("${cmd_yad[@]}" 2>/dev/null)"
        [ -n "$result" ] || return    # package kde-gtk-config should remove possible gtk related yad warnings...

        # New values
        period="$(            echo "$result" | cut -d '|' -f $field_nr)" ; ((++field_nr))
        keepcount="$(         echo "$result" | cut -d '|' -f $field_nr)" ; ((++field_nr))
        delete_uninstalled="$(echo "$result" | cut -d '|' -f $field_nr)" ; ((++field_nr))

        # ad hoc value checks
        [ "$(echo "$keepcount" | sed 's|[0-9]||g')" = "" ] || DIE "sorry, keep count value '$keepcount' is not a number"
        [ $keepcount -le $keepcount_max  ]                 || DIE "sorry, keep count value '$keepcount' is more than $keepcount_max and not supported"

        case "$period" in
            daily | weekly | monthly) ;;
            *) DIE "sorry, cleaning period '$period' is unsupported" ;;
        esac

        case "$delete_uninstalled" in
            TRUE | FALSE) ;;
            *) DIE "sorry, value '$delete_uninstalled' for removing uninstalled packages is unsupported" ;;
        esac
    fi

    # Build the final paccache command list.

    # Clean up cache now and periodically

    if [ "$delete_uninstalled" = "TRUE" ] ; then
        cmd_ruk="paccache $options -ruk0"
    fi

    if [ "$keepcount $period $delete_uninstalled" != "$current_keepcount $current_period $current_delete_uninstalled" ] || [ "$first_time" = "yes" ] ; then
        cmd_period="paccache $options -rk$keepcount"

        if [ ! -r $service ] ; then
            AddCommand "cp $dir2/$pt $timer"
            AddCommand "cp $dir2/paccache.service $service"
        fi
        # Allow ExecStart line with both /usr/bin/paccache or just paccache.
        AddCommand "sed -i $service -e 's|^ExecStart=paccache .*$|ExecStart=$cmd_period|' -e 's|^ExecStart=/usr/bin/paccache .*$|ExecStart=$cmd_period|'"
        AddCommand "sed -i $timer -e 's|^OnCalendar=.*$|OnCalendar=$period|'"
        AddCommand "systemctl enable --now $pt"
        AddCommand "systemctl daemon-reload"
    fi
    if [ -n "$cmd_ruk" ] ; then
        AddCommand "$cmd_ruk"
    fi

    # Execute the command list.

    if [ "$cmds" != ":" ] ; then
        AddCommand --silent "echo Service reloaded."
        if [ "$verbose" = "yes" ] ; then
            # pkexec bash -c "cat '$vfile' ; $cmds"
            RunInTerminal "cat \"$vfile\"; $EOS_ROOTER \"$cmds\""
            rm -f "$vfile"
        else
            # pkexec bash -c "$cmds"
            if [ "$verbose" = "yes" ] ; then
                RunInTerminal "cat \"$vfile\"; $EOS_ROOTER \"$cmds\""
            else
                RunInTerminal "echo \"Running selected commands.\"; $EOS_ROOTER \"$cmds\""
            fi
        fi
    else
        # echo "No change to settings."
        local msg="Nothing to do (settings not changed)"
        eos_yad --form --image=$ICO_INFO --title="$progname" --text="$msg" --button=yad-quit:1 --scroll
    fi
}

_paccache_cleaner_manager "$@"
