#!/bin/bash

    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.

    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.

    # You should have received a copy of the GNU General Public License
    # along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Dotsmenu: a dmenu script to quickly edit configuration files that are
# stored in a "dotfiles" directory.  Opens a {,new }terminal running the
# EDITOR on the selected file, else defaults to the VISUAL.
#
# Part of my dotfiles: https://gitlab.com/protesilaos/dotfiles.
#
# Debian Buster dependencies:
# 	apt install suckless-tools
#
# Optional dependencies:
# 	apt install fd-find libnotify-bin

if [ -d "$HOME/dotfiles" ]; then
	my_dots="$HOME/dotfiles"
else
	echo "ERROR: Your dotfiles are not available"
	echo "Aborting"
	exit 1
fi

# NOTE this would not work with the Xresources, Xdefaults, etc..  It is
# trivial to add them, though I do not use any of them…
my_configs() {
	local my_conf

	# fdfind is just easier to write, but you do not really need it
	if [ "$(command -v fdfind 2> /dev/null)" ]; then
		my_conf="$(fdfind -H -t f '.*rc$|.*\.conf|config$' $my_dots)"
	else
		# HELP can this be simplified further?
		my_conf="$(find "$my_dots" -type d -name '.git' -prune -o -type f -regex ".*\(rc\|\.conf\|config\)$" -print)"
	fi

	# Use parameter expansion to exclude $HOME/dotfiles/ from the results
	# (no need to invoke `sed`).
	echo "${my_conf//$my_dots\//}" | sort
}

# Custom dmenu command.  Accepts the line height as an argument.
my_dmenu() {
	local my_colours my_font menu_height

	my_colours="$HOME/.local/share/my_colours/active-tempus-theme.sh"
	my_font="$HOME/.local/share/my_custom_ui_font.sh"

	source_file() {
		if [ -f "$1" ]; then
			source "$1"
		else
			echo "ERROR: Could not find active $2"
			echo "Aborting"
			exit 1
		fi
	}

	source_file "$my_colours" 'Tempus theme'
	source_file "$my_font" 'UI font'

	if [ -n "$1" ]; then
		menu_height="$1"
	else
		menu_height="8"
	fi

    dmenu -i -p 'Edit selected dotfile' \
	-nb "$background" -nf "$foreground" -sb "$color13" \
	-sf "$background" -fn "$my_custom_ui_font" -l "$menu_height"
}

# Will send a desktop notification if the necessary command is present.
# This function accepts a single argument with the notification message.
my_notify() {
	# TODO test the "$#" condition and feedback
	if [ "$#" == 1 ]; then
		if [ "$(command -v notify-send 2> /dev/null)" ]; then
			notify-send -i applications-system "Dotsmenu" "$1"
		fi

		echo "$1"
	else
		echo "ERROR. my_notify() cannot accept multiple arguments"
		echo "You passed $# arguments"
		echo "Aborting"
		exit 1
	fi
}

# Capture the dmenu output
dotsmenu_interaction="$(my_configs | my_dmenu 12)"
dotsmenu_selection="$my_dots/$dotsmenu_interaction"

# Open the selected file in the editor, else exit.
if [ -n "$dotsmenu_interaction" ]; then
	# TODO can these be turned into a case statement or something more
	# elegant?
	if [ -n "$EDITOR" ]; then
		"$EDITOR" "$dotsmenu_selection"
	elif [ -n "$VISUAL" ]; then
		my_notify "Opening selection in a separate window, using $VISUAL"
		"$VISUAL" "$dotsmenu_selection"
	elif [ "$(command -v gvim 2> /dev/null)" ]; then
		my_notify "Opening selection in GUI Vim"
		gvim "$dotsmenu_selection"
	else
		my_notify "Opening selection using the MIME default"
		xdg-open "$dotsmenu_selection"
	fi
else
	exit
fi
