#compdef kickpass

(( $+functions[_kp_safes] )) ||
_kp_safes()
{
	local files expl

	files=(${(f)"$(_call_program files kickpass ls 2>/dev/null)"})
	_wanted safe expl "Safe" _multi_parts / files
}

(( $+functions[_kp_path] )) ||
_kp_path()
{
	local files expl

	paths=(${(f)"$(_call_program files kickpass ls 2>/dev/null | sed 's#\(.*/\)[^/]\+$#\1#' | sort -u)"})
	_wanted path expl "Path" _multi_parts / paths
}

(( $+functions[_kp-help] )) ||
_kp-help()
{
	_arguments \
		'(-): :->command' \
		&& return

	case $state in
		(command)
			_kp_commands
			;;
	esac
}

(( $+functions[_kp-init] )) ||
_kp-init()
{
	# Nothing
}

(( $+functions[_kp-create] )) ||
_kp-create()
{
	_arguments \
		{-g,--generate}'[Randomly generate a password]' \
		{-l,--length}='[Length of the generated passwerd]' \
		*:'Safe name:' && return
}

(( $+functions[_kp-cat] )) ||
_kp-cat()
{
	_arguments \
		{-p,--password}'[Print password]' \
		{-m,--metadata}='[Print metadata]' \
		:'Safe to open:->safe' && return

	case $state in
		(safe)
			_alternative 'safe::_kp_safes'
			;;
	esac

	return
}

(( $+functions[_kp-edit] )) ||
_kp-edit()
{
	_arguments \
		{-p,--password}'[Edit password]' \
		{-m,--metadata}='[Edit metadata]' \
		:'Safe to edit:->safe' && return

	case $state in
		(safe)
			_alternative 'safe::_kp_safes'
			;;
	esac

	return
}

(( $+functions[_kp-copy] )) ||
_kp-copy()
{
	_arguments \
		:'Safe to copy:->safe' && return

	case $state in
		(safe)
			_alternative 'safe::_kp_safes'
			;;
	esac

	return
}

(( $+functions[_kp-list] )) ||
_kp-list()
{
	_arguments \
		:'Path to list:->path' && return

	case $state in
		(path)
			_alternative 'safe::_kp_path'
			;;
	esac

	return
}

(( $+functions[_kp-delete] )) ||
_kp-delete()
{
	_arguments \
		:'Safe to delete:->safe' && return

	case $state in
		(safe)
			_alternative 'safe::_kp_safes'
			;;
	esac

	return
}

(( $+functions[_kp-rename] )) ||
_kp-rename()
{
	_arguments \
		:'Safe to edit:->safe' \
		:'New safe name:' && return

	case $state in
		(safe)
			_alternative 'safe::_kp_safes'
			;;
	esac

	return
}

(( $+functions[_kp_commands] )) ||
_kp_commands()
{
	local -a kp_commands
	kp_commands=(
		help:'Get some help' \
		init:'Initialize a new password safe directory' \
		{create,new,insert}:'Create a new password safe' \
		{cat,show}:'Open a password safe and print its content on stdout' \
		edit:'Edit a password safe with $EDIT' \
		copy:'Copy a password (first line of safe) into X clipboard' \
		{list,ls}:'List available safes' \
		{delete,rm,remove,destroy}:'Delete a password safe' \
		{rename,mv,move}:'Rename a password safe'
		agent:'Start a kickpass agent in background' \
	)

	_tags kp-commands
	_describe -t kp-commands 'main kickpass commands' kp_commands

	return
}

_kickpass()
{
	local curcontext=$curcontext state line

	_arguments -C : \
		{-v,--version}'[Print kickpass version]' \
		{-h,--help}'[Print help]'\
		'(-): :->command' \
		'(-)*:: :->option-or-argument' \
		&& return

	case $state in
		(command)
			_kp_commands
			;;
		(option-or-argument)
			local cmd cmds
			typeset -A cmds

			# Define aliases
			cmds=()

			# help
			cmds[help]=help

			# init
			cmds[init]=init

			# create
			cmds[create]=create
			cmds[new]=create
			cmds[insert]=create

			# cat
			cmds[cat]=cat
			cmds[show]=cat

			# edit
			cmds[edit]=edit

			# copy
			cmds[copy]=copy

			# list
			cmds[list]=list
			cmds[ls]=list

			# delete
			cmds[delete]=delete
			cmds[rm]=delete
			cmds[remove]=delete
			cmds[destroy]=delete

			# rename
			cmds[rename]=rename
			cmds[move]=rename
			cmds[mv]=rename

			# agent
			cmds[agent]=agent

			cmd=$cmds[$words[1]]

			(( $+cmds[$words[1]] )) || cmd=$words[1]

			curcontext=${curcontext%:*:*}:kp-$words[1]:
			if ! _call_function ret _kp-$cmd; then
				_message "unknown sub-command: $cmd"
			fi
			;;
	esac

	return
}

_kickpass
