#!/bin/sh

#this module can work for all users, so I use common directories
po_domain="alterator-xkb"
cachedir=
ticketdir="/var/lib/alterator/tickets"

if [ -n "$TMPDIR" ]; then
    cachedir="$TMPDIR/alterator-xkb"
else
    cachedir="/var/cache/alterator/alterator-xkb"
fi

#turn off auto expansion
set -f

. alterator-sh-functions

dump_cache()
{
    local langlist="$(write_language "$in_language")"
    local firstlang="${langlist%%:*}"
    LC_ALL="$firstlang" LANGUAGE="$langlist" xkbdatadump
}

clear_cache()
{
    rm -rf "$cachedir"
}

init_cache()
{
    local rc=0
    local msg=
    [ -d "$cachedir/$1" ] && return 0

    mkdir -p "$cachedir/$1"

    cd "$cachedir/$1"
    msg="$(dump_cache 2>&1)"
    rc=$?
    cd - >/dev/null

    [ "$rc" -eq 0 ] ||  write_error "$msg"

    return $rc
}

list_model()
{
    string_quote "$cachedir/$1/models"|
	sed -nr 's,^([^[:space:]]+)[[:space:]]+(.*),("\1" label "\2"),p'
}

list_grp()
{
    string_quote "$cachedir/$1/options"|
	sed -nr 's,^([^[:space:]]+)[[:space:]]+(.*),("\1" label "\2"),p'
}

list_layout()
{
    string_quote "$cachedir/$1/layouts"|
	sed -nr 's,^([[:alnum:]]+)[[:space:]]+(.*),("\1" label "\2"),p'
}

list_variant()
{
    string_quote "$cachedir/$1/layouts"|
	sed -nr "s,^$2(\\([^\\)]+\\))?[[:space:]]+(.+),(\"$2\\1\" label \"\\2\"),p" "$cachedir/$1/layouts"
}

read_current_layout()
{
    if [ -f "$cachedir/current_layout" ];then
	cat "$cachedir/current_layout"
    else
	xkbmapconf -l|tee "$cachedir/current_layout"
    fi
}

list_current_layout()
{
    read_current_layout|
    while read layout; do
	local name="$(grep -m1 "^$layout[[:space:]]" "$cachedir/$1/layouts" | cut -f2)"
	[ -n "$name" ] || name="$layout"
	printf '("%s" label "%s")' "$layout" "$name"
    done
}

write_add()
{
    grep -qs "^$1\$" "$cachedir/current_layout" ||
	echo "$1" >>"$cachedir/current_layout"
}

write_remove()
{
ed -s "$cachedir/current_layout" 2>/dev/null <<EOF
/$1/d
wq
EOF
}

write_up()
{
ed -s "$cachedir/current_layout" 2>/dev/null <<EOF
/$1/m/$1/--
wq
EOF
}

write_down()
{
ed -s "$cachedir/current_layout" 2>/dev/null <<EOF
/$1/m/$1/+
wq
EOF
}

### tickets
clear_ticket()
{
    find "$ticketdir"  -mindepth 1 -maxdepth 1 -type f -name 'xkb-ticket-*' -delete
}

find_ticket()
{
    find "$ticketdir"  -mindepth 1 -maxdepth 1 -type f -name 'xkb-ticket-*' -print -quit
}

make_ticket()
{
    [ -d "$ticketdir" ] || install -d -m755 "$ticketdir"

    name="$ticketdir/xkb-ticket-$(uuidgen)"

    cat>"$name"<<EOF
#!/bin/sh
setxkbmap -option && setxkbmap \$(cat /etc/X11/xinit/Xkbmap)
EOF
    chmod 755 "$name"
    echo "$name"
}

get_ticket()
{
    local ticket="$(find_ticket)"
    [ -n "$ticket" ] || ticket="$(make_ticket)"

    echo "${ticket##*/}"
}

read_firefox()
{
    local ticket="$(get_ticket)"

    printf 'alt-exec-description "%s"' "`_ "Apply saved keyboard settings"`"
    printf 'alt-exec-error-message "%s"' "`_ "Apply failed"`"
    printf 'alt-exec-command "%s"' "${ticket};`_ "Apply"`"
}


### main part

exit_handler()
{
    local rc=$?
    trap - EXIT

    clear_ticket
    clear_cache

    exit $rc
}

trap exit_handler HUP INT QUIT TERM EXIT

clear_ticket
clear_cache

on_message()
{
	case "$in_action" in
		list)
		    [ -n "$in_language" ] || in_language="en_US.UTF-8"
		    local l="$in_language"

		    init_cache "$l" || return

		    echo '('
		    case "$in__objects" in
			avail_model) list_model  "$l" ;;
			avail_grp) list_grp  "$l" ;;
			avail_layout) list_layout  "$l" ;;
			avail_layout/*)
			    local layout="${in__objects%%/avail_variant}"
			    layout="${layout##*/}"
			    list_variant  "$l" "$layout"
			;;
			current_layout) list_current_layout "$l";;
		    esac
		    echo ')'
		    ;;
		read)
		    echo '('

		    read_firefox

		    printf 'model "%s"' "$(xkbmapconf -m)"
		    printf 'grp "%s"' "$(xkbmapconf -g)"
		    [ -s "$cachedir/selected_layout" ] &&
			printf 'layout "%s"' "$(cat "$cachedir/selected_layout")"
		    echo ')'
		    ;;
		write)
		    case "$in__objects" in
			avail_layout*)
			    write_add "$in_variant"
			    ;;
			*)
			    [ -n "$in_layout" ] && echo "$in_layout" >"$cachedir/selected_layout"
			    if [ -n "$in_remove" ];then
				write_remove "$in_layout"
			    elif [ -n "$in_up" ];then
				write_up "$in_layout"
			    elif [ -n "$in_down" ];then
				write_down "$in_layout"
			    elif [ -n "$in_submit" ];then
				xkbmapconf -s -- \
				    -model "$in_model" \
				    -option "$in_grp" \
				    -layout "$(cat "$cachedir/current_layout" | tr '\n' ','| sed s/,$//)"
				[ "$in_update" = "#t" ] &&
				    setxkbmap -option && 
				    setxkbmap $(cat /etc/X11/xinit/Xkbmap) >/dev/null 2>/dev/null
			    fi
			    ;;
		    esac
		    write_nop
		    ;;
		*)
		    echo '#f'
		    ;;
	esac
}

message_loop
