#!/usr/bin/env bash
###############################################################################
# dread — Browse research library via dmenu, open in Zathura
#
# Maintainer:   Kris Yotam <krisyotam@pm.me>
# License:      MIT
# Created:      2026-02-15
#
# Top-level categories:
#   Papers        → ~/research/library/papers/     (field → subfield → PDF)
#   Texts         → ~/research/library/texts/       (textbooks by field)
#   Primary Texts → ~/research/library/primary-texts/ (drama, essays, fiction, poetry)
#   Books         → ~/Calibre Library/               (personal library via Calibre)
#
# All files opened in Zathura.
###############################################################################

LIBRARY="$HOME/research/library"
CALIBRE="$HOME/Calibre Library"

###############################################################################
# helpers
###############################################################################

# Drill into a directory: show subdirs, then files. Recurse on subdir selection.
browse_dir() {
    local dir="$1"
    local prompt="$2"

    while true; do
        # Build list: subdirectories first, then readable files
        local items=""

        # Subdirectories (with trailing /, skip hidden)
        while IFS= read -r d; do
            [ -z "$d" ] && continue
            local dname
            dname=$(basename "$d")
            [[ "$dname" == .* ]] && continue
            items+="󰉋  ${dname}/"$'\n'
        done < <(find "$dir" -mindepth 1 -maxdepth 1 -type d | sort)

        # Files (PDF, EPUB, DJVU, etc.)
        while IFS= read -r f; do
            [ -z "$f" ] && continue
            local name
            name=$(basename "$f")
            case "$name" in
                *.pdf)  items+="  $name"$'\n' ;;
                *.epub) items+="  $name"$'\n' ;;
                *.djvu) items+="  $name"$'\n' ;;
                *.mobi) items+="  $name"$'\n' ;;
                *.cbz)  items+="󰋩  $name"$'\n' ;;
                *)      items+="  $name"$'\n' ;;
            esac
        done < <(find "$dir" -mindepth 1 -maxdepth 1 -type f \( -name "*.pdf" -o -name "*.epub" -o -name "*.djvu" -o -name "*.mobi" -o -name "*.cbz" \) | sort)

        [ -z "$items" ] && { notify-send "dread" "Empty: $(basename "$dir")"; return; }

        local choice
        choice=$(printf '%s' "$items" | sed '/^$/d' | dmenu -i -l 20 -p "$prompt")
        [ -z "$choice" ] && return

        # Strip icon prefix
        local name
        name=$(echo "$choice" | sed 's/^[^ ]* *//')

        if [[ "$name" == */ ]]; then
            # Directory selected — recurse
            name="${name%/}"
            browse_dir "$dir/$name" "  $name"
        else
            # File selected — open in zathura
            zathura "$dir/$name" &>/dev/null & disown
            return
        fi
    done
}

# Browse Calibre library — flat list of all books via metadata.db
browse_calibre() {
    local db="$CALIBRE/metadata.db"
    if [ ! -f "$db" ]; then
        notify-send "dread" "Calibre Library not found"
        return
    fi

    # Query all books: "Title — Author" with path
    local entries
    entries=$(sqlite3 "$db" "
        SELECT b.title, COALESCE(a.name, 'Unknown'), b.path,
               COALESCE(d.format, 'pdf'), COALESCE(d.name, b.title)
        FROM books b
        LEFT JOIN books_authors_link bal ON bal.book = b.id
        LEFT JOIN authors a ON a.id = bal.author
        LEFT JOIN data d ON d.book = b.id
        WHERE d.format IS NOT NULL
        ORDER BY b.title
    " 2>/dev/null)

    [ -z "$entries" ] && { notify-send "dread" "No books in Calibre"; return; }

    # Build dmenu list and parallel path array
    local menu=""
    local -a paths=()

    while IFS='|' read -r title author relpath fmt fname; do
        [ -z "$title" ] && continue
        local ext
        ext=$(echo "$fmt" | tr '[:upper:]' '[:lower:]')
        menu+="  ${title} — ${author}"$'\n'
        paths+=("$CALIBRE/$relpath/$fname.$ext")
    done <<< "$entries"

    local choice
    choice=$(printf '%s' "$menu" | sed '/^$/d' | dmenu -i -l 20 -p "  Books")
    [ -z "$choice" ] && return

    # Find matching index (avoid Plan 9 grep which lacks -F)
    local idx=-1
    local i=0
    while IFS= read -r line; do
        [ -z "$line" ] && continue
        if [[ "$line" == "$choice" ]]; then
            idx=$i
            break
        fi
        ((i++))
    done < <(printf '%s' "$menu" | sed '/^$/d')
    [[ $idx -lt 0 ]] && return

    local file="${paths[$idx]}"

    if [ -f "$file" ]; then
        zathura "$file" &>/dev/null & disown
    else
        notify-send "dread" "File not found: $(basename "$file")"
    fi
}

###############################################################################
# main
###############################################################################

CHOICE=$(printf '%s\n' \
    "  Papers" \
    "  Texts" \
    "  Primary Texts" \
    "  Books" \
| dmenu -i -l 4 -p "󰂺  Library")

[ -z "$CHOICE" ] && exit 0

case "$CHOICE" in
    *Papers*)        browse_dir "$LIBRARY/papers"        "  Papers" ;;
    *Texts*)         browse_dir "$LIBRARY/texts"         "  Texts" ;;
    *Primary\ Texts*) browse_dir "$LIBRARY/primary-texts"  "  Primary" ;;
    *Books*)         browse_calibre ;;
esac
