#!/usr/bin/env bash
###############################################################################
# dnotes — Browse and create notes in ~/notes/ via dmenu
#
# Maintainer:   Kris Yotam <krisyotam@pm.me>
# License:      MIT
# Created:      2026-02-15
# Updated:      2026-02-24
#
# Lists note folders with nerd icons in dmenu. Selecting a folder lists
# its .md files for opening in Emacs. A "Create" option at the bottom
# prompts for frontmatter and creates a new .md note.
#
# Usage:
#   dnotes
###############################################################################

NOTES_DIR="$HOME/notes"

###############################################################################
# folder icons
###############################################################################

declare -A ICONS=(
    [cards]="󰘸"
    [index]="󰮮"
    [jottings]=""
    [marginalia]="󰆏"
    [slipbox]="󱉟"
)

CREATE_ICON=""
DEFAULT_ICON="󰎞"

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

get_icon() {
    local folder="$1"
    echo "${ICONS[$folder]:-$DEFAULT_ICON}"
}

slugify() {
    echo "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g; s/--*/-/g; s/^-//; s/-$//'
}

open_in_emacs() {
    local file="$1"
    # Check if emacsclient can reach a running GUI Emacs
    if emacsclient -e "(window-system)" 2>/dev/null | grep -q "x"; then
        # GUI Emacs running with server — open in vertical split pane (like SPC p n)
        emacsclient -e "(progn
            (split-window-right 80)
            (other-window 1)
            (find-file \"$file\")
            (raise-frame)
            (select-frame-set-input-focus (selected-frame))
            (evil-normal-state))" 2>/dev/null
    else
        # No GUI Emacs — launch one with the file
        emacs "$file" &
    fi
}

###############################################################################
# create note
###############################################################################

create_note() {
    # Pick folder for new note
    local MENU=""
    for folder in slipbox jottings marginalia index cards; do
        [ -d "$NOTES_DIR/$folder" ] && MENU+="$(get_icon "$folder")  $folder"$'\n'
    done

    local CHOICE
    CHOICE=$(printf '%s' "$MENU" | sed '/^$/d' | dmenu -i -l 10 -p "$CREATE_ICON  Create in")
    [ -z "$CHOICE" ] && exit 0

    local FOLDER
    FOLDER=$(echo "$CHOICE" | sed 's/^[^ ]* *//')

    # Prompt for title
    local TITLE
    TITLE=$(printf '' | dmenu -p "󰏫  Title:")
    TITLE=$(echo "$TITLE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    [ -z "$TITLE" ] && exit 0

    local SLUG
    SLUG=$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | sed 's/ /-/g; s/[^a-z0-9-]//g; s/--*/-/g; s/^-//; s/-$//')

    # Prompt for tags (comma-separated)
    local TAGS_INPUT
    TAGS_INPUT=$(echo "" | dmenu -p "  Tags (comma-separated, e.g. math, calculus):")
    # Format as YAML list: "math, calculus" → "[math, calculus]"
    local TAGS="[]"
    if [ -n "$TAGS_INPUT" ]; then
        TAGS="[${TAGS_INPUT}]"
    fi

    # Prompt for certainty
    local CERTAINTY
    CERTAINTY=$(printf 'possible\ncertain\nlikely\nunlikely\nspeculative' | dmenu -i -l 5 -p "  Certainty:")
    [ -z "$CERTAINTY" ] && CERTAINTY="possible"

    # Prompt for importance (1-10)
    local IMPORTANCE
    IMPORTANCE=$(printf '1\n2\n3\n4\n5\n6\n7\n8\n9\n10' | dmenu -i -l 10 -p "  Importance:")
    [ -z "$IMPORTANCE" ] && IMPORTANCE="5"

    # Prompt for preview
    local PREVIEW
    PREVIEW=$(echo "" | dmenu -p "  Preview:")

    local DATE
    DATE=$(date +%Y-%m-%d)

    local FILEPATH="$NOTES_DIR/$FOLDER/${SLUG}.md"

    if [ -f "$FILEPATH" ]; then
        notify-send "dnotes" "Note already exists: $SLUG"
        exit 1
    fi

    cat > "$FILEPATH" <<EOF
---
id: $SLUG
start: $DATE
finish:
certainty: $CERTAINTY
status: seed
importance: $IMPORTANCE
preview: $PREVIEW
tags: $TAGS
---

# $TITLE

EOF

    open_in_emacs "$FILEPATH"
    notify-send "dnotes" "Created: $FOLDER/$SLUG.md"
}

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

# Build folder menu
MENU=""
for folder in slipbox jottings marginalia index cards; do
    [ -d "$NOTES_DIR/$folder" ] && MENU+="$(get_icon "$folder")  $folder"$'\n'
done
MENU+="  create"

# Select folder or create
CHOICE=$(printf '%s' "$MENU" | sed '/^$/d' | dmenu -i -l 10 -p "󰎞  Notes")
[ -z "$CHOICE" ] && exit 0

# Check if Create was selected
SELECTED=$(echo "$CHOICE" | sed 's/^[^ ]* *//')
if [ "$SELECTED" = "create" ]; then
    create_note
    exit 0
fi

FOLDER="$SELECTED"

# List .md files in folder
FILES=$(find "$NOTES_DIR/$FOLDER" -maxdepth 1 -name "*.md" -type f | sort)

if [ -z "$FILES" ]; then
    notify-send "dnotes" "No notes in $FOLDER"
    exit 1
fi

# Build file menu from markdown titles
FILE_MENU=""
while IFS= read -r filepath; do
    filename=$(basename "$filepath" .md)
    # Extract title from # heading
    title=$(grep -m1 '^# ' "$filepath" | sed 's/^# *//')
    [ -z "$title" ] && title="$filename"
    FILE_MENU+="$title  [$filename]"$'\n'
done <<< "$FILES"

# Select file
FILE_CHOICE=$(printf '%s' "$FILE_MENU" | sed '/^$/d' | dmenu -i -l 20 -p "$(get_icon "$FOLDER")  $FOLDER")
[ -z "$FILE_CHOICE" ] && exit 0

# Extract slug from selection
SLUG=$(echo "$FILE_CHOICE" | sed 's/.*\[//; s/\]//')
MD_FILE="$NOTES_DIR/$FOLDER/${SLUG}.md"

if [ -f "$MD_FILE" ]; then
    open_in_emacs "$MD_FILE"
else
    notify-send "dnotes" "File not found: $SLUG.md"
    exit 1
fi
