#!/bin/sh
# Copyright Joel Beckmeyer 2020-2021
# Copyright Florian Fischer 2022
# wofi-pass is licensed under the term of GPL-2.
# A copy of the license can be found in the LICENSE file or at
# https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt

set -eu

autotype=0
help=0
head=0
TYPE_CMD="wl-copy"

if [ -x "$(command -v -p wofi 2>/dev/null)" ] ; then
    menu_cmd='wofi --dmenu --style=/etc/wofi/style.css'
else
    menu_cmd='rofi -dmenu'
fi

_trim() {
    var="$*"
    # remove leading whitespace characters
    var="${var#"${var%%[![:space:]]*}"}"
    # remove trailing whitespace characters
    var="${var%"${var##*[![:space:]]}"}"
    printf '%s' "$var"
}

# the explicit newlines here are funky, but needed due to command substitution
# stripping trailing newlines so `printf '%s\n' "$line"` cannot be used
_parse_fields() {
	has_username=0
	fields="$(pass show "$password" | tail -n +2 | cut -d: -f1 -s)"
	field_list="password
"
	for line in $fields; do
		if [ "$line" = "user" ]; then
			has_username=1
			field_list="$field_list$line
"
		elif [ "$line" = "otpauth" ]; then
			field_list="${field_list}OTP
"
		else
			field_list="$field_list$line
"
		fi
	done
	if [ "$TYPE_CMD" = "wtype -" ] && [ "$has_username" -eq 1 ]; then
		printf "autotype
"
	fi
	printf '%s' "$field_list"
}

_pass_field() {
	_trim "$(pass show "$password" | tail -n+2 | grep "^${*}:.*" | cut -d: -f1 -s --complement)"
}

_pass_get() {
	if [ "$1" = "password" ]; then
		pass show "$password" | { IFS= read -r pass; printf %s "$pass"; }
	elif [ "$1" = "OTP" ]; then
		pass otp "$password" | tail -n1 | { IFS= read -r pass; printf %s "$pass"; }
	else
		_pass_field "$@"
	fi
}

_usage() {
	printf "Usage: wofi-pass [options]\n"
	printf "	-a, --autotype	autotype whatever entry is chosen\n"
	printf "	-h, --help	show this help message\n"
	printf "	-1, --head	select the first line of the password file\n"
	printf "	-t, --type	type the selection instead of copying to clipboard\n"
}

OPTS="$(getopt --options ah1t --longoptions autotype,help,head,type -n 'wofi-pass' -- "$@")"
eval set -- "$OPTS"
while true; do
	case "$1" in
		-a | --autotype		) autotype=1; shift ;;
		-h | --help			) help=1; shift ;;
		-1 | --head			) head=1; shift ;;
		-t | --type			) TYPE_CMD="wtype -"; shift;;
		-- ) shift; break ;;
		*  ) break ;;
	esac
done

if [ "$help" -eq 1 ]; then
	_usage >&2
	exit 0
fi

cd "${PASSWORD_STORE_DIR:-$HOME/.password-store}"
password_files="$(find . -name "*.gpg" | sed "s/^\.\/\(.*\)\.gpg$/\1/")"

password=$(printf '%s\n' "$password_files" | eval "${menu_cmd}")
[ -n "$password" ] || exit
if [ "$head" -eq 1 ]; then
	_pass_get "password" | $TYPE_CMD
	exit
fi

field_list="$(_parse_fields)"
nfields=$(printf '%s\n' "$field_list" | wc -l)
if [ "$autotype" -ne 1 ]; then
	field='password'
	if  [ "$nfields" -gt 1 ]; then
		field=$(printf '%s\n' "$field_list" | eval "${menu_cmd}")
	fi

	if [ "$field" != "autotype" ]; then
		_pass_get "$field" | $TYPE_CMD
		exit
	fi
fi

username=$(_pass_get "user")
password=$(_pass_get "password")
printf '%s\t%s\n' "$username" "$password" | $TYPE_CMD
