#!/bin/sh

#this module can work for all users, so I use common directories
alterator_api_version=1
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
}


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\t%s\n' "$layout" "$name"
    done
}

list_avail_variant()
{
    grep "^$2\((\|[[:space:]]\)" "$cachedir/$1/layouts"
}


list_avail_layout()
{
    grep '^\([[:alnum:]]\+\)[[:space:]]\+' "$cachedir/$l/layouts"|
    LANG="${in_language%%:*}.UTF-8" sort -k 2,2 2>/dev/null
}

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##*/}"
}

### 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"
		    local l="$in_language"

		    init_cache "$l" || return

		    case "$in__objects" in
			avail_model) cat "$cachedir/$l/models"|write_enum ;;
			avail_grp) cat "$cachedir/$l/options"|write_enum ;;
			avail_layout) list_avail_layout|write_enum;;
			current_layout) list_current_layout "$l"|write_enum;;
			avail_variant)
			    [ -n "$in_name" ] || in_name="$(list_avail_layout|head -n1|cut -f1)"
			    list_avail_variant  "$l" "$in_name"|write_enum
			    ;;
		    esac
		    ;;
		read)
		    #firefox extension
		    local ticket="$(get_ticket)"
		    write_string_param alt_exec_description "`_ "Apply saved keyboard settings"`"
		    write_string_param alt_exec_error_message "`_ "Apply failed"`"
		    write_string_param alt_exec_command "${ticket};`_ "Apply"`"

		    local model="$(xkbmapconf -m)"
		    [ -n "$model" ] || model="pc104"

		    write_string_param model "$model"
		    write_string_param grp "$(xkbmapconf -g)"
		    [ -s "$cachedir/selected_layout" ] &&
			write_string_param layout "$(cat "$cachedir/selected_layout")"
		    ;;
		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
		    ;;
	esac
}

message_loop
