#!/bin/sh

PATH="/usr/lib/alterator-x11:$PATH"

DATADIR="/usr/share/alterator-x11"
TICKETDIR="/var/lib/alterator/tickets"


XORGCONFIG_MAIN="/etc/X11/xorg.conf"
XORGCONFIG_TEMPLATE="$DATADIR/xorg.conf"
XORGCONFIG_WORKCOPY="/etc/X11/xorg.conf.alterator"

XORGDRV_DIR="$(getconf LIBDIR)/X11/modules/drivers"


XCONFTOOL="/usr/bin/xconf"
SETUPDRVTOOL="/usr/bin/x11setupdrv"
XTESTTOOL="/usr/bin/xtest_wrapper"

set -f
. /usr/share/alterator/build/backend3.sh
. shell-regexp



#### xorg config functions

xorg_config_name()
{
	if [ -f "$XORGCONFIG_WORKCOPY" ] ;then
		echo "$XORGCONFIG_WORKCOPY"
	else
		echo "$XORGCONFIG_MAIN"
	fi
}

made_workcopy()
{
	if [ -f "$XORGCONFIG_MAIN" ] ;then
		cp "$XORGCONFIG_MAIN" "$XORGCONFIG_WORKCOPY"
	else
		cp "$XORGCONFIG_TEMPLATE" "$XORGCONFIG_WORKCOPY"
		mouse_autosetup -c "$XORGCONFIG_WORKCOPY" xorg
		video_autosetup "$XORGCONFIG_WORKCOPY"
	fi
}

sure_workcopy()
{
	[ -f "$XORGCONFIG_WORKCOPY" ]  || made_workcopy
}


clear_workcopy()
{
	[ -f "$XORGCONFIG_WORKCOPY" ] && rm -f "$XORGCONFIG_WORKCOPY"
}

commit_workcopy()
{
    [ -f "$XORGCONFIG_WORKCOPY" ] && mv -f "$XORGCONFIG_WORKCOPY" "$XORGCONFIG_MAIN"
    "$SETUPDRVTOOL" "$XORGCONFIG_MAIN" >&2 #setup correct GL symlinks for the current config file
}

###helper functions
_()
{
LANG=${in_language%%;*}.utf8 gettext "alterator-x11" "$1"
}

out_option()
{
    [ -n "$2" ] && printf '%s "%s"' "$1" "$2"
}

in_option()
{
    sed -nr "s,^$1[[:space:]],,p"
}

clear_ddc()
{
    ddcclean
}


#read autodetect information
read_autodetect_data()
{
	#video data
	local data="$(video_scan)"
	auto_cardname="$(echo "$data"|in_option cardname)"
	auto_xdepth="$(echo "$data"|in_option xdepth)"

	auto_xdriver="$(echo "$data"|in_option xdriver)"	
	auto_xdrivername="$(echo "$data"|in_option xdrivername)"

	#monitor data
	auto_monitor="$(monitor_scan)"

	[ -n "$auto_monitor" ] || auto_monitor="Monitor 1024x768"
	[ -n "$auto_xdriver" ] || auto_xdriver="vesa"
	
	#recommended resolution
	local size="$(ddcsize)"
	if [ -n "$size" ];then
	    auto_xresolution="$(ddcreslist|ddcresbest "${size% *}" "${size#* }")"
	fi
}

#### get functions
get_monitor()
{
    local monitor="$($XCONFTOOL -n "$1"| cut -f1 -d'|')"
    [ -n "$monitor" ] || monitor="$auto_monitor"

    echo "$monitor"
}

get_first_monitor()
{
    mondrv |
	grep  -m1 "^$(quote_sed_regexp "$1");"|
	cut -f2 -d';'|
	sed -r 's,^[[:space:]]*,,'
}

get_vendor()
{
    mondrv |
	grep -m1 "[^;]\+;[[:space:]]*$(quote_sed_regexp "$1");"|
	cut -f1 -d';'
}

#### ticket functions
clear_ticket()
{
    find "$TICKETDIR"  -mindepth 1 -maxdepth 1 -type f -name 'xorg-ticket-*' -delete
}

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

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

    name="$TICKETDIR/xorg-ticket-$(uuidgen)"
    
    cat>"$name"<<EOF
#!/bin/sh
LANG=${in_language%%;*}.utf8 "$XTESTTOOL" "$XORGCONFIG_WORKCOPY"
EOF
    chmod 755 "$name"
    echo "$name"
}

get_ticket()
{
    local ticket="$(find_ticket)"
    
    [ -n "$ticket" ] || ticket="$(make_ticket)"
    
    echo "${ticket##*/}"
}


#### read functions

read_firefox()
{
    local ticket="$(get_ticket)"
    
    out_option "alt-exec-description" "`_ "Test current display settings"`"
    out_option "alt-exec-error-message" "`_ "Test failed"`"
    out_option "alt-exec-command" "${ticket};`_ "Test"`"
}

#### write functions


#### list functions
print_recommended()
{
    [ "$1" = "$2" ] && printf -- ' - %s' "`_ "recommended"`"
}

print_xdepth()
{
    printf '("%s" description "%s" label "%s%s")' "$1"  "$2" "$2" "$(print_recommended "$1" "$3")"
}

list_xdepth()
{
    local xdriver="$($XCONFTOOL -d "$1")"
    [ -n "$xdriver" ] || xdriver="$auto_xdriver"

    local xdepth_list=$(echo "$xdriver" | vcinfo | sed -nr '/^xdlist/ s,xdlist[[:space:]]+,,p')
    local recomm_xdepth=$(echo "$xdriver" | vcinfo | in_option xdepth)
    
    for i in $xdepth_list; do
	case $i in
	    8) print_xdepth 8 "`_ "256 colors (8 bit)"`" $recomm_xdepth;;
    	    15) print_xdepth 15 "`_ "32 thousand colors (15 bits)"`" $recomm_xdepth ;;
    	    16) print_xdepth 16 "`_ "65 thousand colors (16 bits)"`" $recomm_xdepth ;;
    	    24) print_xdepth 24 "`_ "16 million colors (24 bits)"`" $recomm_xdepth ;;
	    32) print_xdepth 32 "`_ "4 billion colors (32 bits)"`" $recomm_xdepth ;;
	     *) print_xdepth $i "$i `_ "bits"`" $recomm_xdepth ;;
	esac
    done
}

list_xresolution()
{
    local res="$(ddcreslist)"
    [ -n "$res" ] || res="$(cat "$DATADIR/resolutions")"

    printf '("auto")'
    for i in $res;do
	printf '("%s" label "%s%s")' "$i" "$i" "$(print_recommended "$i" "$auto_xresolution")"
    done
}

list_xdriver()
{
    local IFS='	'
    find "$XORGDRV_DIR" -name '*_drv.so'|
	sed -r 's,.*/([a-z0-9]+)_drv\.so$,\1,'|
	video_drivers|
	sort|
	while read driver description rest; do
	    printf '("%s" description "%s" label "%s - %s%s")' \
		"$driver" \
		"$description" \
		"$driver" \
		"$description" \
		"$(print_recommended "$driver" "$auto_xdriver")"
	done
}

list_model()
{
    local config="$(xorg_config_name)"
    local monitor="$(get_monitor "$config")"
    local vendor="$(get_vendor "$monitor")"

    if [ -n "$vendor" ]; then
	mondrv|
	    grep "^$(quote_sed_regexp "$vendor");"|
	    cut -f2 -d';'|
	    sort -u|
	    sed -r 's,^[[:space:]]*(.*),("\1"),'
    else
	printf '("%s")' "$monitor"
    fi
}

list_vendor()
{
    printf '("%s" label "%s")' "auto" "`_ "Automatically detected"`"
    mondrv|
	cut -f1 -d';'|
	sort -u|
	sed 's,.*,("&"),'
}

#### exit handler and initialization

exit_handler()
{
	trap - TERM HUP EXIT

	[ -f "$XORGCONFIG_MAIN" ] && "$SETUPDRVTOOL" >&2
	clear_workcopy
	clear_ddc
	clear_ticket
}

trap exit_handler TERM HUP EXIT

[ -x /usr/sbin/x11presetdrv ] && /usr/sbin/x11presetdrv >&2 ||: #sure we use right nvidia.xinf files
clear_workcopy #remove workcopy
clear_ddc #remove ddc cache
clear_ticket
read_autodetect_data #detect video hardware



on_message()
{
	case "$in_action" in
		constraints)
		    echo '('
		    printf 'auto_monitor (label "%s")' "`_ "Monitor"`"
		    printf 'auto_cardname (label "%s")' "`_ "Video card"`"
		    printf 'monitor (label "%s")' "`_ "Monitor"`"
		    printf 'xdriver (label "%s")' "`_ "Video driver"`"
		    printf 'xdepth (label "%s")' "`_ "Color depth"`"
		    printf 'xresolution (label "%s")' "`_ "Color resolution"`"
		    printf 'onboot (label "%s" default #f)' "`_ "Start graphical interface on system booting"`"
		    echo ')'
		    ;;
		list)
		    local config="$(xorg_config_name)"
		    echo '('
			case "${in__objects##*/}" in
			    avail_xdepth)
				list_xdepth "$config"
				;;
			    avail_xresolution)
				list_xresolution
				;;
			    avail_xdriver)
				list_xdriver
				;;
			    avail_model)
				list_model
				;;
			    avail_vendor)
				list_vendor
				;;
			esac
		    echo ')'
		    ;;
		read)
			local config="$(xorg_config_name)"
			echo '('
			if [ "$in__objects" = "monitor" ];then
				local monitor=$(get_monitor "$config")
				out_option vendor "$(get_vendor "$monitor")"
			else
				read_firefox
				#autodetect
				out_option auto_cardname "$auto_cardname"
				out_option auto_monitor "$auto_monitor"

				#config
				[ -f "$config" ] || printf 'config_status "(%s)"\n' "`_ "config file doesn\'t exist"`"

				local xdriver="$($XCONFTOOL -d "$config")"
				local xdepth="$($XCONFTOOL -c "$config")"
				local xresolution="$($XCONFTOOL -r "$config")"

				#fill missing values using autodetect data
				[ -n "$xdriver" ] || xdriver="$auto_xdriver"
				[ -n "$xdepth" ] || xdepth="$auto_xdepth"
				[ -n "$xresolution" ] || xresolution="$auto_xresolution"

				#calculate driver name
				out_option monitor "$(get_monitor "$config")"
				out_option xdriver "$xdriver"
				out_option xdrivername "$(echo "$xdriver"|video_drivers|cut -f2)"
				out_option xdepth "$xdepth"
				out_option xresolution "$xresolution"

			fi
			echo ')'
			;;
		write)
    			sure_workcopy
			local config="$(xorg_config_name)"
			
			if [ "$in__objects" = "/" ]; then
			    [ -n "$in_monitor" ] && monitor_setup "$in_monitor" "$config"
			    [ -n "$in_xdepth" ] && $XCONFTOOL -C "$in_xdepth" "$config" "$config"
			    [ -n "$in_xresolution" ] && $XCONFTOOL -R "$in_xresolution" "$config" "$config"

			    [ "$in_commit" = '#f' -o "$in_async" = 'yes' ] || commit_workcopy

			    echo '()'
			elif [ "$in__objects" = "driver" ]; then
			    if [ -n "$in_xdriver" ]; then 
			      video_setup "$in_xdriver" "$config"
			      local recomm_xdepth=$(echo "$in_xdriver" | vcinfo | in_option xdepth)
			      [ -n "$recomm_xdepth" ] && 
			        $XCONFTOOL -C "$recomm_xdepth" "$config" "$config"
			    fi
			    
			    echo '()'
			elif [ "$in__objects" = "monitor" ] ;then
			    if [ "$in_vendor" = "auto" ];then
				monitor="$auto_monitor"
			    else
				monitor="$(get_first_monitor "$in_vendor")"
			    fi
			    [ -n "$monitor" ] && monitor_setup "$monitor" "$config"
			    echo '()'
			elif [ "$in__objects" = "test" ] ;then
			    if [ ! -f "$XORGCONFIG_WORKCOPY" ];then
				printf '(error "%s")' "`_ "no workcopy was found"`"
				return;
			    fi
			    if ! LANG=${in_language%%;*}.utf8 $XTESTTOOL "$XORGCONFIG_WORKCOPY"; then
				printf '(error "%s")' "`_ "X11 test failed"`"
				return;
			    fi
			    echo '()'
			fi
			;;
			
		*)
			echo '#f'
			;;
	esac
}

message_loop
