#!/usr/bin/env bash

STATUS_FILE=/dev/shm/polybar_task_manager
BAR_CONFIG_FILE=~/.config/polybar/bar.ini
MODULES_LEFT_FILE=~/.config/polybar/modules-left.ini
REFRESH=1
TASK_MENU="  Open a new one #  Close"

update_bar_config()
{
base_config=$(grep -e "^modules-left-dynamic *= *" $BAR_CONFIG_FILE | cut -f 3- -d " " )
new_config="taskslabel"

for task in $(seq 1 "$1"); do

    cat <<MODULE_TEMPLATE
[module/taskbar$task]
type = custom/ipc
hook-0 = echo ""
hook-1 = ~/.config/polybar/scripts/task_manager --set-task $task
hook-2 = ~/.config/polybar/scripts/task_manager --show-or-minimize-window $task
hook-3 = ~/.config/polybar/scripts/task_manager --close-window $task
hook-4 = ~/.config/polybar/scripts/task_manager --show-menu $task
click-left = polybar-msg -p %pid% hook taskbar$task 3
click-middle = polybar-msg -p %pid% hook taskbar$task 4
click-right = polybar-msg -p %pid% hook taskbar$task 5

MODULE_TEMPLATE

new_config="$new_config taskbar$task"
done

echo "modules-left = $base_config $new_config" > $MODULES_LEFT_FILE
}

create_module_tasklabel()
{
cat <<TASKLABEL_TEMPLATE
[module/taskslabel]
type = custom/ipc
hook-0 = echo "%{T4}Tasks:%{T-}"
hook-1 = echo ""
; click-left = rofi -modi window -show window -theme $ROFI_THEME -show-icons -location 1 -yoffset +45 -xoffset +20
click-left = dbus-send --session --type=method_call \
             --dest=org.gnome.Shell /org/gnome/Shell org.gnome.Shell.Eval string:'Main.overview.show();'
TASKLABEL_TEMPLATE
}

get_icon_by_name()
{
    name=$(echo "$1" | tr '[:upper:]' '[:lower:]')
    declare -A ICON_MAP=(
        [tilix]=
        [code]=
        [brave-browser]=
        [firefox]=
        [chromium]=
        [tor]=
        [nextcloud]=
        [gnome-calculator]=
        [gnome-calendar]=
        [gnome-control-center]=
        [gnome-terminal]=
        [gpaste-ui]=
        [eog]=
        [evince]=
        [gimp-210]=
        [nautilus]=
        [file-roller]=
        [keepassxc]=
        [steam]=
        [skype]=
        [slack]=
        [spotify]=
        [telegramdesktop]=
    )

    if [ ${ICON_MAP[$name]+_} ]; then
        echo "${ICON_MAP[$name]}"
    else
        echo "$name" | cut -c 1 | tr '[:lower:]' '[:upper:]'
    fi
}

show_tasks()
{
    max_tasks=$(grep -cE "^\[module/taskbar[0-9]+]" ~/.config/polybar/task_manager.ini)
    wmctrl -lxp | awk '{if ($2 > -1) print $4,$1,$3}' \
                | sed -r 's/([0-9])\.([0-9])/\1\2/g' \
                | awk -F'.' '{ print $NF }' \
                | tail -"$max_tasks" | sort > $STATUS_FILE.current

    if [ -f $STATUS_FILE.active ]; then
        if [ "$(get_task_id "$(cat $STATUS_FILE.active)")" = "$(get_active_window)" ]; then
            diff -q $STATUS_FILE $STATUS_FILE.current > /dev/null 2>&1
            if [ $? -ne 1 ]; then
                rm -rf $STATUS_FILE.current
                return 0
            fi
        fi
    fi

    mv $STATUS_FILE.current $STATUS_FILE

    num_windows=$(wc -l $STATUS_FILE | cut -f 1 -d " ")

    if [ "$num_windows" -eq 0 ]; then
        polybar-msg hook taskslabel 2 > /dev/null
    else
        polybar-msg hook taskslabel 1 > /dev/null
    fi

    for counter in $(seq 1 "$max_tasks"); do
        if [ "$counter" -le "$num_windows" ]; then
            polybar-msg hook taskbar"$counter" 2 > /dev/null
        else
            polybar-msg hook taskbar"$counter" 1 > /dev/null
        fi

        sleep 0.1
    done
}

print_task_icon()
{
    name=$(sed "${1}q;d" $STATUS_FILE | cut -f 1 -d " " | tr '[:upper:]' '[:lower:]')
    icon=$(get_icon_by_name "$name")

    if [ "$(get_task_id "$1")" = "$(get_active_window)" ]; then
        echo '%{T6}%{F#F5A70A}'"$icon"'%{F-}%{T-}'
        if [ -f $STATUS_FILE.active ]; then
            polybar-msg hook "taskbar$(cat $STATUS_FILE.active)" 2 > /dev/null
        fi
        echo "$1" > $STATUS_FILE.active
    else
        echo '%{T6}'"$icon"'%{T-}'
    fi
}

show_task_menu()
{
    pid=$(get_task_pid "$1")
    cmd=$(ps --no-headers -o cmd "$pid" \
            | sed 's/--gapplication-service//g' \
            | tr -d '\n')
    offset=$(( ($1 * 65) ))
    ROFI="rofi -dmenu -sep # -theme $ROFI_THEME
                -location 1 -width 8
                -yoffset +45 -xoffset +${offset}"
    choice=$(echo "$TASK_MENU" | $ROFI -theme-str 'inputbar { children: [];}' \
              | sed 's/^[[:space:]]*//' | cut -f 1 -d " ")

    case "$choice" in
        Open)
            $cmd &>/dev/null &
        ;;
        Close)
            id=$(get_task_id "$1")
            wmctrl -ic "$id"
        ;;
    esac

    print_task_icon "$1"
}

get_active_window()
{
    echo 0x0"$(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2 | cut -f 2 -d 'x')"
}

get_task_id()
{
    sed "${1}q;d" $STATUS_FILE | cut -f 2 -d " "
}

get_task_pid()
{
    sed "${1}q;d" $STATUS_FILE | cut -f 3 -d " "
}

daemon()
{
    while true; do
        show_tasks
        sleep $REFRESH
    done
}

case "$1" in
    --daemon)
        > /dev/shm/polybar_task_manager
        daemon
    ;;
    --generate-config)
        create_module_tasklabel > ~/.config/polybar/task_manager.ini
        update_bar_config "$2" >> ~/.config/polybar/task_manager.ini
    ;;
    --set-task)
        print_task_icon "$2"
    ;;
    --show-menu)
        show_task_menu "$2"
    ;;
    --show-or-minimize-window)
        id=$(get_task_id "$2")

        if [ "$id" = "$(get_active_window)" ]; then
            xdotool getactivewindow windowminimize
        else
            wmctrl -ia "$id"
        fi
        print_task_icon "$2"
    ;;
    --close-window)
        id=$(get_task_id "$2")
        wmctrl -ic "$id"
    ;;
esac

exit 0