#!/usr/bin/env sh
# Fzf searching notmuch email database

# Search with notmuch queries
# You can either invoke:
# `fzfmail` -> and then interactively create a notmuch query (not fuzzy searching)
# or:
# `fzfmail [notmuchquery]` -> pre-craft a query and then use fzf to filter it further, e.g.
# fzfmail tag:archived and subject:Important and not tag:flagged
#
# select as many mails as you wish (ctrl-a for all current results)
# preview mails with ?
#
# read with <enter>
# re-tag with <ctrl-t>

if exist fzf; then
    # Allow fuzzy search filtering of a notmuch search query
    fzfmail() {
        # shellcheck disable=2016 # we only want the expression to expand when fzf preview is actually called not by the shell
        if [ -z "$1" ]; then
            # interactive query
            fzfmail_mails=$(
                printf "
\nStart a notmuch search query:\n" |
                    fzf --multi \
                        --header "tag: | from: | to: | subject: | folder: | date: || and | not | or | near | adj || <enter> read | <ctrl-t> tag" \
                        --bind "change:reload:notmuch search {q} || true" \
                        --bind "ctrl-a:toggle-all" \
                        --bind '?:toggle-preview' \
                        --expect 'ctrl-t,esc' \
                        --preview='notmuch show --part=1 $(echo {} | cut -d" " -f1)' \
                        --preview-window hidden \
                        --phony |
                    cut -d" " -f1
            )
        else
            # pre-queried fuzzy search
            fzfmail_mails=$(
                notmuch search "$*" |
                    fzf --multi \
                        --header "<enter> read | <ctrl-t> tag" \
                        --bind "ctrl-a:toggle-all" \
                        --bind '?:toggle-preview' \
                        --expect 'ctrl-t,esc' \
                        --preview='notmuch show --part=1 $(echo {} | cut -d" " -f1)' \
                        --preview-window hidden |
                    cut -d" " -f1
            )
        fi

        # find out expected action
        fzfmail_action=$(echo "$fzfmail_mails" | head -n1)
        # quit on esc pressed -- do not do anything with selected results
        if echo "$fzfmail_action" | grep -qe 'esc'; then return 0; fi

        # get the selected mails
        fzfmail_mails=$(echo "$fzfmail_mails" | tail -n+2)

        # tag mails
        if echo "$fzfmail_action" | grep -qe 'ctrl-t'; then
            printf "current tags: %s\n" "$(notmuch search --output=tags "$fzfmail_mails" | tr '\n' ' ')"
            printf "add tags with +tag; remove with -tag\n"
            printf "apply tags: "
            read -r fzfmail_tags
            notmuch tag "$fzfmail_tags" -- "$fzfmail_mails"
            return 0
        fi

        # display the mails, in semi-readable format
        # highlight subject line in color
        # allow moving through results with n/p
        notmuch show "$fzfmail_mails" | sed -e 's/^\fmessage{.*$/MESSAGE:/' -e '/^\f[a-z]/d' -e 's/^Subject:/\o033[41mSubject:\o033[0m/' | less --pattern '^MESSAGE:$' -R

        unset fzfmail_mails
        unset fzfmail_action
        unset fzfmail_tags
    }
fi
