#!/bin/bash
# jamesbond 2016
#
# This is unfinished script, it sorta works but xinput_calibrator itself
# does not always work.
# 
# Note: uses bash for associative arrays

### config
APPTITLE="Calibrate Touchscreen"
PROG="xinput_calibrator"
XORG_CONF_D=/etc/X11/xorg.conf.d
CAL_FN=99-calibration.conf

### globals
unset devices
declare -A devices

########### GUI helper ###########
check_root_and_terminal() {
	test -z "$DISPLAY" && ! test -t 1 && exit 1 # not running in terminal, exit
	if test $(id -u) -ne 0; then
		msg "You need to be root to do this."
		exit 1
	fi
}

dlg() {
	if [ "$DISPLAY" ]; then
		Xdialog --title "$APPTITLE" "$@"
	else
		dialog --backtitle "$APPTITLE" "$@"
	fi
}

info() {
	if [ "$DISPLAY" ]; then
		if [ "$1" ]; then
			[ $XPID ] && kill $XPID
			Xdialog --title "$APPTITLE" --no-buttons --infobox "$@" 0 0 1000000 &
			XPID=$!
		else
			kill $XPID
			XPID=
		fi
	else
		dlg --infobox "$@" 15 60
	fi
}

msg() {
	if [ "$DISPLAY" ]; then
		dlg --msgbox "$@" 0 0
	else
		dlg --msgbox "$@" 15 60
	fi
	
}

checklist() {
	if [ "$DISPLAY" ]; then
		dlg --separator " " --stdout --checklist "$@"
	else
		dlg --stdout --checklist "$@"
	fi
}

menu_notags() {
	if [ "$DISPLAY" ]; then
		dlg --separator " " --stdout --no-tags --menu "$@"
	else
		dlg --stdout --no-tags --menu "$@"
	fi
}

fselect() {
	if [ "$DISPLAY" ]; then
		dlg --separator " " --stdout --backtitle "$1" --fselect "$2" 0 0
	else
		dlg --stdout --backtitle "$1" --fselect "$2" 0 0
	fi
}

progressbox() {
	if [ "$DISPLAY" ]; then
		dlg --backtitle "$1" --no-cancel --tailbox - "$2" "$3" 
	else
		dlg --progressbox "$@" 18 76
	fi
}

# $1-text, returns true/false
yesno() {
	if [ "$DISPLAY" ]; then
		dlg --yesno "$1" 0 0
	else
		dlg --yesno "$1" 15 60
	fi	
}


############ functional helper #############
# returns ${devices} array
get_devices() {
	eval $(xinput_calibrator --list | sed 'h;s|.*id=|devices[|;s|$|]=|;x;s|.* "|"|;s|" .*|"|;H;x;s|\n||')
}

# $1-device name
get_device_id() {
	local p
	for p in ${!devices[@]}; do
		[ "$1" = "${devices[$p]}" ] && echo $p && return
	done 	
}

### main
if ! type $PROG > /dev/null || ! type xinput > /dev/null; then
	msg "xinput_calibrator or xinput is missing. Can't do my job."
	exit 1
fi

if [ -z $DISPLAY ]; then
	info "This program only works under X11 desktop."
	exit 1
fi

# 1. get devices list
get_devices
items=
for p in ${!devices[@]}; do
	items="$items \"${devices[$p]}\" \"${devices[$p]}\""
done 

# 2. select which device to calibrate
if selected=$(eval menu_notags "test" 15 40 15 $items); then

	# 3. Check if supported (we only support Evdev)
	if xinput --list-props "$(get_device_id "$selected")" | grep -q Evdev; then
	
		# 4. Calibrate
		output=$($PROG --device "$selected" --output-type xorg.conf.d)
		case "$output" in
			*InputClass*)
			
				# 5. Save settings
				if yesno "Keep this calibration for all subsequent sessions?\nThis will override previous calibrations."; then
					echo "$output" | 
					sed "/Section/,/EndSection/!d;s|!!Name_Of_TouchScreen!!|$selected|"  > $XORG_CONF_D/$CAL_FN
					msg "Calibration stored in $XORG_CONF_D/$CAL_FN"
				else
					msg "Calibration only applied for this session."
				fi
				exit
				;;
		esac
	else
		msg "Only devices using evdev driver is supported."
	fi
fi
msg "Opoeration cancelled. Nothing changed."
