#!/usr/bin/env sh

set -eu

# shellcheck source=/usr/share/jq.sh/jq.sh
. "$(jq.sh)"

# shellcheck source=SCRIPTDIR/../lib/core.sh
. "/usr/share/zellij-selector/core.sh"
# shellcheck source=SCRIPTDIR/../lib/getoptions.sh
. "/usr/share/zellij-selector/getoptions.sh"

getoptions_error() {
    printf '%s\n' "$1"
    return $ERR_INVALID_OPTION
}

getoptions_parse "$@"
eval "set -- $REST"

if [ $# -gt 0 ]; then
    printf 'Unrecognized argument: %s\n' "$1"
    exit "$ERR_INVALID_ARGUMENT"
fi

CONF='{
    "zellijBin": "zellij",
    "dialogBin": "whiptail",
    "allowNesting": true,
    "showNewSessionAuto": true,
    "showNewSessionNamed": true,
    "showKillAndDeleteAll": true,
    "sessionPrefix": "",
    "allowUserConfiguration": true,
    "noSessionShells": [
        "fish",
        "zsh",
        "bash"
    ],
    "exitAfterShell": false,
    "colors": {
        "root": ["", "black"],
        "window": ["", "black"],
        "border": ["white", "black"],
        "title": ["white", "black"],
        "textbox": ["white", "black"],
        "compactbutton": ["white", "black"],
        "button": ["black", "white"],
        "listbox": ["white", "black"],
        "actsellistbox": ["black", "white"],
        "actlistbox": ["black", "white"],
        "entry": ["white", "black"]
    }
}'

read_config() {
    if command -v "$JQ" > /dev/null; then
        if conf="$(jq_read "$conf_file")"; then
            CONF="$(JQ=jq jq_merge "$CONF" "$conf")"
        elif [ $? -eq $JQ_READ_ERROR ]; then
            printf 'Error in %s: %s\n' "$conf_file" "$conf"
        fi
    fi
}

read_configs() {
    for conf_file in "$@"; do
        if [ -f "$conf_file" ]; then
            case "${conf_file##*.}" in
                json)
                    JQ=jq read_config "$conf_file"
                ;;
                yaml|yml)
                    JQ=yq read_config "$conf_file"
                ;;
                toml)
                    JQ=tomlq read_config "$conf_file"
                ;;
            esac
        fi
    done
}

read_configs "/usr/etc/zellij-selector."* "/usr/etc/zellij-selector.d/"*

if jq_test "$CONF" '.allowUserConfiguration'; then
    read_configs "${XDG_CONFIG_HOME:-"$HOME/.config"}/zellij-selector."* "${XDG_CONFIG_HOME:-"$HOME/.config"}/zellij-selector.d/"*
fi

zellij="$(jq_get "$CONF" -r '.zellijBin')"
if ! command -v "$zellij" > /dev/null; then
    printf 'No zellij binery found at %s.\n' "$zellij"
    exit $ERR_NO_ZELLIJ_BINERY
fi

dialog="$(jq_get "$CONF" -r '.dialogBin')"
if ! command -v "$dialog" > /dev/null; then
    printf 'No dialog binery found at %s.\n' "$dialog"
    exit $ERR_NO_DIALOG_BINERY
fi

newt_colors="$(jq_get "$CONF" -r '.colors | map_values(join(",")) | to_entries | map("\(.key)=\(.value)") | join(":")')"
dialog() {
    NEWT_COLORS="$newt_colors" command "$dialog" --title 'zellij-selector' "$@" 3>&1 1>&2 2>&3
}

if [ -n "${ZELLIJ-}" ] || [ -n "${ZELLIJ_SESSION_NAME-}" ]; then
    if jq_test "$CONF" '.allowNesting'; then
        if ! dialog --defaultno --yesno 'Current zellij session found.\nZellij does not support nesting.\nContinue anyway?' 0 0; then
            exit
        fi
    else
        dialog --msgbox 'Current zellij session found. Nesting is disabled.' 0 0
        exit
    fi
fi

get_items() {
    items='[]'

    if sessions_keys="$("$zellij" list-sessions -ns 2> /dev/null)"; then
        if sessions_labels="$("$zellij" list-sessions -n 2> /dev/null)"; then
            sessions_keys="$(jq_get "$sessions_keys" -R | jq -s)"
            sessions_labels="$(jq_get "$sessions_labels" -R | jq -s)"
            items="$(jq -n --argjson items "$items" --argjson keys "$sessions_keys" --argjson labels "$sessions_labels" '[range($keys | length)] | reduce .[] as $i ($items; . + [["attach", $keys[$i]] | @json, $labels[$i]])')"
        fi
    fi

    if jq_test "$CONF" '.showNewSessionAuto'; then
        items="$(echo "$items" | jq '. + [["auto"] | @json, "New session"]')"
    fi

    if jq_test "$CONF" '.showNewSessionNamed'; then
        items="$(echo "$items" | jq '. + [["named"] | @json, "New named session"]')"
    fi

    if jq_test "$CONF" '.showKillAndDeleteAll'; then
        items="$(echo "$items" | jq '. + [["killAndDeleteAll"] | @json, "Kill & delete all sessions"]')"
    fi

    for i in $(jq_seq "$CONF" '.noSessionShells'); do
        # shellcheck disable=SC2016
        shell="$(jq_get "$CONF" --argjson i "$i" '.noSessionShells[$i]')"
        command="$(jq_get "$shell" -r 'if type == "array" then .[0] else . end')"
        if command -v "$command" > /dev/null; then
            # shellcheck disable=SC2016
            items="$(jq_get "$items" --argjson i "$i" --argjson shell "$shell" '. + [["noSession", $i] | @json, "No session [\($shell | @sh)]"]')"
        fi
    done

    echo "$items"
}

exitAfterShell="$(jq_get "$CONF" '.exitAfterShell | booleans')"
while selection="$(get_items | jq_eval '["dialog", "--notags", "--menu", "Select shell entry point:", "0", "0", "0"] + .')"; do
    case "$(jq_get "$selection" -r '.[0]')" in
        attach)
            "$zellij" attach -- "$(jq_get "$selection" -r '.[1]')"
            "$exitAfterShell" && exit
        ;;
        auto)
            "$zellij"
            "$exitAfterShell" && exit
        ;;
        named)
            if session_name="$(dialog --inputbox 'Enter new session name:' 0 0)"; then
                session_name="$(jq_get "$CONF" -r '.sessionPrefix')$session_name"
                "$zellij" attach -c -- "$session_name"
                "$exitAfterShell" && exit
            fi
        ;;
        killAndDeleteAll)
            zellij delete-all-sessions -fy
        ;;
        noSession)
            # shellcheck disable=SC2016
            jq_eval "$CONF" --argjson selection "$selection" '.noSessionShells[$selection[1]]'
            "$exitAfterShell" && exit
        ;;
    esac
done
