#!/bin/bash
# -*- mode: sh; tab-width: 8; encoding: utf-8-unix -*-

prog=`basename $0 .bash`
PREFIX=/usr/local
ROLE=gpgkey

. /usr/local/bin/usr_local_tput.bash

[ -n "$GPG_TTY" ] && TTY=$GPG_TTY
[ -x "$GPG_TTY" ] && TTY=`tty`

## _is_found
_is_found() {
    # returns 0 if binary is found in path
    [[ -z $1 ]] && return 1
    command -v "$1" 1>/dev/null 2>/dev/null
    return $?
}

# Synopsis: option_is_set -flag [out]
#
# First argument is the commandline flag (e.g., "-s").
# If the second argument is present and set to 'out', print out the
# result: either 'set' or 'unset' (useful for if conditions).
#
# Return 0 if is set, 1 otherwise
## option_is_set
option_is_set() {
    local -i r	 # the return code (0 = set, 1 = unset)

    ##	[[ -n "${(k)OPTS[$1]}" ]];
    r=1
    return $r;
}

## echo_assuan_getpin
function echo_assuan_getpin() {
    # simply prints out commands for pinentry's stdin to activate the
    # password dialog
    cat << EOF
OPTION ttyname=$TTY
OPTION lc-ctype=$LANG
SETTITLE $title
SETDESC $description
SETPROMPT Password:
GETPIN
EOF
	return 0
}


# Ask user for a password
# Wraps around the pinentry command, from the GnuPG project, as it
# provides better security and conveniently use the right toolkit.
## ask_password
ask_password() {

    local description="$1"
    local title="${2:-Enter password.}"
    local output
    local password
    local gtkrc
    local theme
    local pass_asked

    # Distributions have broken wrappers for pinentry: they do
    # implement fallback, but they disrupt the output somehow.	We are
    # better off relying on less intermediaries, so we implement our
    # own fallback mechanisms. Pinentry supported: curses, gtk-2, qt4, qt5
    # and x11.

    # make sure LANG is set, default to C
    export LANG=${LANG:-C}

    DBUG "asking password with tty=$TTY lc-ctype=$LANG" >&2
    pass_asked=0

    if false && [ -n "$TTY" ]; then
	DBUG "terminal detected" >&2
	if _is_found "gridfire"; then
	    DBUG "gridfire"
	    # SETTITLE $title SETDESC $description
	    output=$(gridfire -H $title)
	    pass_asked=1
	fi
    fi
	
    if [[ ! -z $WAYLAND_DISPLAY ]]; then
	DBUG "wayland display detected" >&2
	if _is_found "pinentry-gnome3" ; then
	    DBUG "using pinentry-gnome3 on wayland" >&2
	    output=$(echo_assuan_getpin | pinentry-gnome3|tr '[\n]' '@' )
	    pass_asked=1
	fi
    fi
    if [[ ! -z $DISPLAY ]] && [[ $pass_asked == 0 ]]; then
	DBUG "X11 display detected" >&2
	if _is_found "pinentry-qt"; then
	    DBUG "using pinentry-qt" >&2
	    output=$(echo_assuan_getpin | pinentry-qt -a beep|tr '[\n]' '@' )
	    pass_asked=1
	elif _is_found "pinentry-qt5"; then
	    DBUG "using pinentry-qt5" >&2
	    output=$(echo_assuan_getpin | pinentry-qt5 -a beep|tr '[\n]' '@' )
	    pass_asked=1
	elif _is_found "pinentry-gtk-2"; then
	    DBUG "using pinentry-gtk2" >&2
	    output=$(echo_assuan_getpin | pinentry-gtk-2|tr '[\n]' '@' )
	    pass_asked=1
	elif _is_found "pinentry-x11"; then
	    DBUG "using pinentry-x11" >&2
	    output=$(echo_assuan_getpin | pinentry-x11|tr '[\n]' '@' )
	    pass_asked=1
	elif _is_found "pinentry-gnome3"; then
	    DBUG "using pinentry-gnome3 on X11" >&2
	    output=$(echo_assuan_getpin | pinentry-gnome3|tr '[\n]' '@' )
	    pass_asked=1
	fi
    fi
    if [[ $pass_asked == 0 ]]; then
	DBUG "no display detected" >&2
	if _is_found "gridfire"; then
	    DBUG "gridfire" >&2
	    # SETTITLE $title SETDESC $description
	    output=$(gridfire -H $title )
	elif _is_found "pinentry-curses"; then
	    DBUG "using pinentry-curses with no display" >&2
	    output=$(echo_assuan_getpin | pinentry-curses|tr '[\n]' '@' )
	    pass_asked=1
	fi
    fi

	[[ $pass_asked == 0 ]] &&
	    ERROR "Cannot find pinentry-curses or gridfire and no DISPLAY detected." >&2 && \
	    return 3
	

	# parse the pinentry output
	local pinentry_error
	sed -e 's/@/\n/g' <<< ${output} | while read i ; do #? (f)
	    [ -z "$i" ] && continue
	    key="${i::2}" ; val="${i:2}";
	    [[ $i =~ ^ERR ]] && {
		pinentry_error="${i:4}"
		WARN $pinentry_error >&2
		continue
	    }
	    # here the password is found
	    if [ "$key" = "D " ] ; then
		password="$val"
		DBUG $i key="${key}" '#'val="${#val}" >&2
		DBUG Password is found >&2
		[ -z "$password" ] && {
		    WARN "Empty password" >&2
		    return 1
		}
 		echo "$password"
		return 0
		
	    else
		DBUG $i key="${i::2}" val="${i:2}" >&2
	    fi
	done

	# if sphinx mode is chosen, use the provided input
	# as master password to retrieve the actual password
#	if option_is_set --sphx-user || option_is_set --sphx-host; then
#		password=$( sphinx_get_password "$password")
#	fi

	return 0
}

# INFO 0=$0
if [ -x /usr/bin/basename ] && \
       [  $( basename -- "$0" .bash ) = $prog \
	 -o $( basename -- "$0" .sh ) = $prog ] ; then
    [ "$#" -eq 1 ] && [ "$1" = '-h' -o "$1" = '--help' ] && \
	echo USAGE: $0 '[decription [title]]' && exit 0
    #	echo USAGE: $0 && grep '^[a-z].*()\|^## ' $0 | sed -e 's/().*//' && exit 0
    #    [ $# -eq 0 ] && set --
    ask_password "$@"
    exit $?
  fi
