#!/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"

alterator_api_version=1

set -f

. alterator-sh-functions
. shell-regexp

#### xorg config functions


commit_workcopy()
{
  [ -f "$XORGCONFIG_WORKCOPY" ] && cp -f "$XORGCONFIG_WORKCOPY" "$XORGCONFIG_MAIN"
  "$SETUPDRVTOOL" "$XORGCONFIG_MAIN" >&2 #setup correct GL symlinks for the current config file
  # remove config-x11's backup to prevent him from overwriting new xorg.conf
  rm -rf /tmp/alterator/config-x11.backup
}


# xdepth and xres depends on selected driver

get_auto_xres(){
  local xdriver="$1"
  if [ "$xdriver" = "fbdev" -a -c "/dev/fb0" ]; then
    echo "$(fbresolution:-"auto")"
    return
  fi
  # recommended resolution
  local size="$(ddcsize)"
  if [ -n "$size" ];then
    auto_xresolution="$(ddcreslist|ddcresbest "${size% *}" "${size#* }")"
  fi
  [ -n "$auto_xresolution" ] || auto_xresolution="auto"
  echo "$auto_xresolution"
}

#autodetect information
read_autodetect_data()
{
	#video data
	ddcclean
	local data="$(video_scan)"

	auto_cardname="$(video_scan -s name)"
	auto_xdriver="$(video_scan -s first)"
	auto_xdrivername="$(video_drv -s desc "$auto_xdriver")"

	#monitor data
	auto_monitor="$(monitor_scan)"

	[ -n "$auto_monitor" ] || auto_monitor="Monitor 1024x768"

	local fbres=
	[ -c "/dev/fb0" ] && fbres=$(fbresolution)
	if [ -z "$auto_xdriver" -a -n "$fbres" ]; then
	   auto_xdriver="fbdev"
	   return
	fi

	[ -n "$auto_xdriver" ] || auto_xdriver="vesa"
}

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


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

print_xdepth()
{
    write_enum_item "$1" "$2$(print_recommended "$1" "$3")"
}

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

    local xdepth_list=$(video_drv -s dlist "$xdriver")
    local recomm_xdepth=$(video_drv -s depth "$xdriver")

    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")"

    local recommended_xres=$(get_auto_xres )
    write_enum_item "auto" "`_ "automatically"`"
    for i in $res;do
	write_enum_item "$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,'| sort |
	while read driver rest; do
	    description="$(video_drv -s desc $driver)"
	    write_enum_item "$driver" "$driver - $description$(print_recommended "$driver" "$auto_xdriver")"
	done
}

list_model(){
    local monitor="$(get_monitor "$XORGCONFIG_WORKCOPY")"
    local vendor="$(get_vendor "$monitor")"
    local IFS=";" #for write_enum

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

list_vendor(){
    local IFS=";" #for write_enum
    write_enum_item "auto" "`_ "Automatically detected"`"
    mondrv|
      cut -f1 -d';'|
      sort -u|
      write_enum
}

#### exit handler and initialization

exit_handler()
{
	trap - TERM HUP EXIT

	[ -f "$XORGCONFIG_MAIN" ] && "$SETUPDRVTOOL" >&2
	rm -f "$XORGCONFIG_WORKCOPY"
	ddcclean
	clear_ticket
}

trap exit_handler TERM HUP EXIT

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

# create initial workcopy
if [ -f "$XORGCONFIG_MAIN" ] ;then
  cp -f "$XORGCONFIG_MAIN" "$XORGCONFIG_WORKCOPY"
else
  x11_autosetup "$XORGCONFIG_WORKCOPY"
fi


on_message()
{
	case "$in_action" in
		list)
			case "${in__objects##*/}" in
			    avail_xdepth)
				list_xdepth "$XORGCONFIG_WORKCOPY"
				;;
			    avail_xresolution)
				list_xresolution
				;;
			    avail_xdriver)
				list_xdriver
				;;
			    avail_model)
				list_model
				;;
			    avail_vendor)
				list_vendor
				;;
			esac
		    ;;
		read)
			case "$in__objects" in
			    monitor)
				local monitor=$(get_monitor "$XORGCONFIG_WORKCOPY")
				write_string_param vendor "$(get_vendor "$monitor")"
				;;
			    *)
				[ -f "/tmp/alterator/config-x11" ] && write_bool_param config_x11 yes

				local ticket="$(get_ticket)"
				write_string_param alt_exec_description "`_ "Test current display settings"`"
				write_string_param alt_exec_error_message "`_ "Test failed"`"
				write_string_param alt_exec_command "${ticket};`_ "Test"`"

				#autodetect
				write_string_param auto_cardname "$auto_cardname"
				write_string_param auto_monitor "$auto_monitor"


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

				#fill missing values using autodetect data
				if [ -z "$xdriver" ]; then
				  xdriver="$auto_xdriver"
				  video_setup "$xdriver" "$XORGCONFIG_WORKCOPY"
				fi
				if [ -z "$xdepth" ]; then
				  xdepth="$(video_drv -s depth "$xdriver")"
				  xconf -C "$xdepth" "$XORGCONFIG_WORKCOPY" "$XORGCONFIG_WORKCOPY"
				fi
				if [ -z "$xresolution" ]; then
				  xresolution="$(get_auto_xres "$xdriver")"
				  resolution_setup "$xresolution" "$XORGCONFIG_WORKCOPY"
				fi

				#calculate driver name
				write_string_param monitor "$(get_monitor "$XORGCONFIG_WORKCOPY")"
				write_string_param xdriver "$xdriver"
				write_string_param xdrivername "$(video_drv -s desc "$xdriver")"
				write_string_param xdepth "$xdepth"
				write_string_param xresolution "$xresolution"
				;;
			esac
			;;
		write)
			if [ ! -f "$XORGCONFIG_WORKCOPY" ];then
			    write_error "`_ "no workcopy was found"`"
			    return;
			fi

			case "$in__objects" in
			    /)
				[ -n "$in_monitor" ] &&\
				  monitor_setup "$in_monitor" "$XORGCONFIG_WORKCOPY"
				[ -n "$in_xdepth" ] &&\
				  $XCONFTOOL -C "$in_xdepth" "$XORGCONFIG_WORKCOPY" "$XORGCONFIG_WORKCOPY"
				[ -n "$in_xresolution" ] && resolution_setup "$in_xresolution" "$XORGCONFIG_WORKCOPY"

				[ "$in_commit" = '#f' -o "$in_async" = 'yes' ] || commit_workcopy
				;;
			    driver)
				if [ -n "$in_xdriver" ]; then
				    video_setup "$in_xdriver" "$XORGCONFIG_WORKCOPY"
				    $XCONFTOOL -C "$(video_drv -s depth "$in_xdriver")" "$XORGCONFIG_WORKCOPY" "$XORGCONFIG_WORKCOPY"
				fi
				;;
			    monitor)
				    if [ "$in_vendor" = "auto" ];then
					    monitor="$auto_monitor"
				    else
					    monitor="$(get_first_monitor "$in_vendor")"
				    fi
				    [ -n "$monitor" ] && monitor_setup "$monitor" "$XORGCONFIG_WORKCOPY"
				;;
			    test)

				# we can't run nv under nvidia and vice versa
				local old_drv=  #"$(xconf -d "$XORGCONFIG_MAIN")"
				# in installer we can't find old driver in $XORGCONFIG_MAIN...
				cat /proc/`pidof X`/maps | grep -q nvidia_drv.so && old_drv=nvidia
				cat /proc/`pidof X`/maps | grep -q nv_drv.so && old_drv=nv
				local new_drv="$(xconf -d "$XORGCONFIG_WORKCOPY")"
				local old_new="$old_drv $new_drv"
				if [ "$old_new" = "nv nvidia" -o "$old_new" = "nvidia nv" ]; then
				  write_error "`_ "Test disabled, because nv and nvidia drivers can not work on your video card simultaneously. Probably if one of them works fine now then the other one would work fine too."`"
				  return
				fi

				if ! LANG=${in_language%%;*}.utf8 $XTESTTOOL "$XORGCONFIG_WORKCOPY"; then
				    local reason="$(sed -n -e 's/^(EE)[[:space:]]*/\n/p' /var/log/Xorg.alterator.test)"
				    write_error "`_ "X11 test failed"` $reason"
				    return;
				fi
				;;
			esac
			;;
	esac
}

message_loop
